Compare commits
No commits in common. "master" and "gh-pages" have entirely different histories.
16710 changed files with 734838 additions and 56948 deletions
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
|
@ -1,8 +0,0 @@
|
||||||
- [ ] I have disclosed use of any AI generated code in my commit messages.
|
|
||||||
- If you are using an LLM, and do not fully understand the changes it is making to the code base, do not create a PR.
|
|
||||||
- In our experience, AI generated code often results in overly complex code that lacks enough context for a proper fix or feature inclusion. This results in considerably longer code reviews. Due to this, AI authored or partially authored PRs may be closed without comment.
|
|
||||||
- [ ] I understand these changes in full and will be able to respond to review comments.
|
|
||||||
- [ ] My change is accurately described in the commit message.
|
|
||||||
- [ ] My contribution is tested and working as described.
|
|
||||||
- [ ] I have read the [Developer Certificate of Origin](https://developercertificate.org/) and certify my contribution under its conditions.
|
|
||||||
|
|
||||||
110
.github/workflows/ci.yml
vendored
110
.github/workflows/ci.yml
vendored
|
|
@ -1,110 +0,0 @@
|
||||||
name: Continuous Integration
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
format:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Rust toolchain
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
components: rustfmt
|
|
||||||
- name: Cargo cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/registry
|
|
||||||
~/.cargo/git
|
|
||||||
key: ${{ runner.os }}-cargo-rust_stable-${{ hashFiles('**/Cargo.toml') }}
|
|
||||||
- name: Format
|
|
||||||
run: cargo fmt -- --check
|
|
||||||
|
|
||||||
tests:
|
|
||||||
needs:
|
|
||||||
- format
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
test_args:
|
|
||||||
- --no-default-features --features "" # for cosmic-comp, don't remove!
|
|
||||||
- --no-default-features --features "winit_debug"
|
|
||||||
- --no-default-features --features "winit_tokio"
|
|
||||||
- --no-default-features --features "winit"
|
|
||||||
- --no-default-features --features "winit_wgpu"
|
|
||||||
- --no-default-features --features "wayland"
|
|
||||||
- --no-default-features --features "applet"
|
|
||||||
- --no-default-features --features "desktop,smol"
|
|
||||||
- --no-default-features --features "desktop,tokio"
|
|
||||||
- -p cosmic-theme
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
- name: Get date for registry cache
|
|
||||||
id: date
|
|
||||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
|
|
||||||
- name: Cargo registry cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/registry/index
|
|
||||||
~/.cargo/registry/cache
|
|
||||||
~/.cargo/git
|
|
||||||
key: ${{ runner.os }}-cargo-registry-${{ steps.date.outputs.date }}
|
|
||||||
restore-keys: ${{ runner.os }}-cargo-registry-
|
|
||||||
- name: System dependencies
|
|
||||||
run: sudo apt-get update; sudo apt-get install -y libxkbcommon-dev libwayland-dev
|
|
||||||
- name: Rust toolchain
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
- name: Test features
|
|
||||||
run: cargo test ${{ matrix.test_args }} -- --test-threads=1
|
|
||||||
env:
|
|
||||||
RUST_BACKTRACE: full
|
|
||||||
|
|
||||||
examples:
|
|
||||||
needs:
|
|
||||||
- format
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
examples:
|
|
||||||
- "application"
|
|
||||||
- "open-dialog"
|
|
||||||
- "context-menu"
|
|
||||||
- "nav-context"
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
- name: Get date for registry cache
|
|
||||||
id: date
|
|
||||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
|
|
||||||
- name: Cargo registry cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cargo/registry/index
|
|
||||||
~/.cargo/registry/cache
|
|
||||||
~/.cargo/git
|
|
||||||
key: ${{ runner.os }}-cargo-registry-${{ steps.date.outputs.date }}
|
|
||||||
restore-keys: ${{ runner.os }}-cargo-registry-
|
|
||||||
- name: System dependencies
|
|
||||||
run: sudo apt-get update; sudo apt-get install -y libxkbcommon-dev libwayland-dev
|
|
||||||
- name: Rust toolchain
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
- name: Check example
|
|
||||||
run: cargo check -p "${{ matrix.examples }}"
|
|
||||||
env:
|
|
||||||
RUST_BACKTRACE: full
|
|
||||||
36
.github/workflows/pages.yml
vendored
36
.github/workflows/pages.yml
vendored
|
|
@ -1,36 +0,0 @@
|
||||||
name: Pages
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
pages:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
- name: Install Rust nightly
|
|
||||||
uses: dtolnay/rust-toolchain@master
|
|
||||||
with:
|
|
||||||
toolchain: nightly-2025-07-31
|
|
||||||
- name: System dependencies
|
|
||||||
run: sudo apt-get update; sudo apt-get install -y libxkbcommon-dev libwayland-dev
|
|
||||||
- name: Build documentation
|
|
||||||
run: |
|
|
||||||
RUSTDOCFLAGS="--cfg docsrs" \
|
|
||||||
cargo +nightly-2025-07-31 doc --no-deps \
|
|
||||||
-p cosmic-client-toolkit \
|
|
||||||
-p cosmic-protocols \
|
|
||||||
-p libcosmic \
|
|
||||||
--verbose --features tokio,winit,wayland,desktop,single-instance,applet,xdg-portal,multi-window
|
|
||||||
- name: Deploy documentation
|
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
publish_dir: ./target/doc
|
|
||||||
force_orphan: true
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1,6 +0,0 @@
|
||||||
.cargo
|
|
||||||
.idea
|
|
||||||
Cargo.lock
|
|
||||||
target
|
|
||||||
vendor
|
|
||||||
vendor.tar
|
|
||||||
7
.gitmodules
vendored
7
.gitmodules
vendored
|
|
@ -1,7 +0,0 @@
|
||||||
[submodule "iced"]
|
|
||||||
path = iced
|
|
||||||
url = https://github.com/pop-os/iced.git
|
|
||||||
branch = master
|
|
||||||
[submodule "icon-theme"]
|
|
||||||
path = cosmic-icons
|
|
||||||
url = https://github.com/pop-os/cosmic-icons
|
|
||||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"rust-analyzer.check.overrideCommand": ["just", "check-json"],
|
|
||||||
"git-blame.gitWebUrl": "",
|
|
||||||
}
|
|
||||||
257
Cargo.toml
257
Cargo.toml
|
|
@ -1,257 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "libcosmic"
|
|
||||||
version = "1.0.0"
|
|
||||||
edition = "2024"
|
|
||||||
rust-version = "1.90"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
name = "cosmic"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = [
|
|
||||||
"winit",
|
|
||||||
"tokio",
|
|
||||||
"a11y",
|
|
||||||
"dbus-config",
|
|
||||||
"x11",
|
|
||||||
"iced-wayland",
|
|
||||||
"multi-window",
|
|
||||||
]
|
|
||||||
advanced-shaping = ["iced/advanced-shaping"]
|
|
||||||
# Accessibility support
|
|
||||||
a11y = ["iced/a11y", "iced_accessibility"]
|
|
||||||
# Enable about widget
|
|
||||||
about = []
|
|
||||||
# Builds support for animated images
|
|
||||||
animated-image = [
|
|
||||||
"dep:async-fs",
|
|
||||||
"image/gif",
|
|
||||||
"image/webp",
|
|
||||||
"image/png",
|
|
||||||
"tokio?/io-util",
|
|
||||||
"tokio?/fs",
|
|
||||||
]
|
|
||||||
# XXX autosize should not be used on winit windows unless dialogs
|
|
||||||
autosize = []
|
|
||||||
applet = [
|
|
||||||
"autosize",
|
|
||||||
"winit",
|
|
||||||
"wayland",
|
|
||||||
"tokio",
|
|
||||||
"cosmic-panel-config",
|
|
||||||
"ron",
|
|
||||||
"multi-window",
|
|
||||||
]
|
|
||||||
applet-token = ["applet"]
|
|
||||||
# Use the cosmic-settings-daemon for config handling on Linux targets
|
|
||||||
dbus-config = []
|
|
||||||
# Debug features
|
|
||||||
debug = ["iced/debug"]
|
|
||||||
# Enables pipewire support in ashpd, if ashpd is enabled
|
|
||||||
pipewire = ["ashpd?/pipewire"]
|
|
||||||
# Enables process spawning helper
|
|
||||||
process = ["dep:libc", "dep:rustix"]
|
|
||||||
# Use rfd for file dialogs
|
|
||||||
rfd = ["dep:rfd"]
|
|
||||||
# Enables desktop files helpers
|
|
||||||
desktop = [
|
|
||||||
"process",
|
|
||||||
"dep:cosmic-settings-config",
|
|
||||||
"dep:freedesktop-desktop-entry",
|
|
||||||
"dep:image-extras",
|
|
||||||
"dep:mime",
|
|
||||||
"dep:shlex",
|
|
||||||
"tokio?/io-util",
|
|
||||||
"tokio?/net",
|
|
||||||
]
|
|
||||||
# Enables launching desktop files inside systemd scopes
|
|
||||||
desktop-systemd-scope = ["desktop", "dep:zbus"]
|
|
||||||
# Enables keycode serialization
|
|
||||||
serde-keycode = ["iced_core/serde"]
|
|
||||||
# Prevents multiple separate process instances.
|
|
||||||
single-instance = ["zbus/blocking-api", "ron"]
|
|
||||||
# smol async runtime
|
|
||||||
smol = ["dep:smol", "iced/smol", "zbus?/async-io", "rfd?/async-std"]
|
|
||||||
tokio = [
|
|
||||||
"dep:tokio",
|
|
||||||
"ashpd?/tokio",
|
|
||||||
"iced/tokio",
|
|
||||||
"rfd?/tokio",
|
|
||||||
"zbus?/tokio",
|
|
||||||
"cosmic-config/tokio",
|
|
||||||
]
|
|
||||||
# Tokio async runtime
|
|
||||||
# Wayland window support
|
|
||||||
iced-wayland = [
|
|
||||||
"ashpd?/wayland",
|
|
||||||
"autosize",
|
|
||||||
"iced/wayland",
|
|
||||||
"iced_winit/wayland",
|
|
||||||
"surface-message",
|
|
||||||
]
|
|
||||||
wayland = [
|
|
||||||
"iced-wayland",
|
|
||||||
"iced_runtime/cctk",
|
|
||||||
"iced_winit/cctk",
|
|
||||||
"iced_wgpu/cctk",
|
|
||||||
"iced/cctk",
|
|
||||||
"dep:cctk",
|
|
||||||
]
|
|
||||||
surface-message = []
|
|
||||||
# multi-window support
|
|
||||||
multi-window = []
|
|
||||||
# Render with wgpu
|
|
||||||
wgpu = ["iced/wgpu", "iced_wgpu"]
|
|
||||||
# X11 window support via winit
|
|
||||||
winit = ["iced/winit", "iced_winit"]
|
|
||||||
winit_debug = ["winit", "debug"]
|
|
||||||
winit_tokio = ["winit", "tokio"]
|
|
||||||
winit_wgpu = ["winit", "wgpu"]
|
|
||||||
# Enables XDG portal integrations
|
|
||||||
xdg-portal = ["ashpd"]
|
|
||||||
qr_code = ["iced/qr_code"]
|
|
||||||
markdown = ["iced/markdown"]
|
|
||||||
highlighter = ["iced/highlighter"]
|
|
||||||
async-std = [
|
|
||||||
"dep:async-std",
|
|
||||||
"ashpd?/async-std",
|
|
||||||
"rfd?/async-std",
|
|
||||||
"zbus?/async-io",
|
|
||||||
"iced/async-std",
|
|
||||||
]
|
|
||||||
x11 = ["iced/x11", "iced_winit/x11"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
apply = "0.3.0"
|
|
||||||
ashpd = { version = "0.12.3", default-features = false, optional = true }
|
|
||||||
async-fs = { version = "2.2", optional = true }
|
|
||||||
async-std = { version = "1.13", optional = true }
|
|
||||||
auto_enums = "0.8.8"
|
|
||||||
cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "160b086", optional = true }
|
|
||||||
jiff = "0.2"
|
|
||||||
cosmic-config = { path = "cosmic-config" }
|
|
||||||
cosmic-settings-config = { git = "https://github.com/pop-os/cosmic-settings-daemon", optional = true }
|
|
||||||
# Internationalization
|
|
||||||
i18n-embed = { version = "0.16.0", features = [
|
|
||||||
"fluent-system",
|
|
||||||
"desktop-requester",
|
|
||||||
] }
|
|
||||||
i18n-embed-fl = "0.10"
|
|
||||||
rust-embed = "8.11.0"
|
|
||||||
css-color = "0.2.8"
|
|
||||||
derive_setters = "0.1.9"
|
|
||||||
futures = "0.3"
|
|
||||||
image = { version = "0.25.10", default-features = false, features = [
|
|
||||||
"ico",
|
|
||||||
"jpeg",
|
|
||||||
"png",
|
|
||||||
] }
|
|
||||||
image-extras = { version = "0.1.0", default-features = false, features = [
|
|
||||||
"xpm",
|
|
||||||
"xbm",
|
|
||||||
], optional = true }
|
|
||||||
libc = { version = "0.2.183", optional = true }
|
|
||||||
log = "0.4"
|
|
||||||
mime = { version = "0.3.17", optional = true }
|
|
||||||
palette = "0.7.6"
|
|
||||||
rfd = { version = "0.16.0", default-features = false, features = [
|
|
||||||
"xdg-portal",
|
|
||||||
], optional = true }
|
|
||||||
rustix = { version = "1.1", features = ["pipe", "process"], optional = true }
|
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
|
||||||
slotmap = "1.1.1"
|
|
||||||
smol = { version = "2.0.2", optional = true }
|
|
||||||
thiserror = "2.0.18"
|
|
||||||
taffy = { version = "0.9.2", features = ["grid"] }
|
|
||||||
tokio = { version = "1.50.0", optional = true }
|
|
||||||
tracing = "0.1.44"
|
|
||||||
unicode-segmentation = "1.12"
|
|
||||||
url = "2.5.8"
|
|
||||||
zbus = { version = "5.14.0", default-features = false, optional = true }
|
|
||||||
float-cmp = "0.10.0"
|
|
||||||
|
|
||||||
# Enable DBus feature on Linux targets
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
|
||||||
cosmic-config = { path = "cosmic-config", features = ["dbus"] }
|
|
||||||
cosmic-settings-daemon = { git = "https://github.com/pop-os/dbus-settings-bindings" }
|
|
||||||
zbus = { version = "5.14.0", default-features = false }
|
|
||||||
|
|
||||||
[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies]
|
|
||||||
freedesktop-icons = { package = "cosmic-freedesktop-icons", git = "https://github.com/pop-os/freedesktop-icons" }
|
|
||||||
freedesktop-desktop-entry = { version = "0.8.1", optional = true }
|
|
||||||
shlex = { version = "1.3.0", optional = true }
|
|
||||||
|
|
||||||
[target.'cfg(any(not(unix), target_os = "macos"))'.dependencies]
|
|
||||||
# Used to embed bundled icons for non-unix platforms.
|
|
||||||
phf = { version = "0.13.1", features = ["macros"] }
|
|
||||||
|
|
||||||
[dependencies.cosmic-theme]
|
|
||||||
path = "cosmic-theme"
|
|
||||||
|
|
||||||
[dependencies.iced]
|
|
||||||
path = "./iced"
|
|
||||||
default-features = false
|
|
||||||
features = [
|
|
||||||
"advanced",
|
|
||||||
"image-without-codecs",
|
|
||||||
"lazy",
|
|
||||||
"svg",
|
|
||||||
"web-colors",
|
|
||||||
"tiny-skia",
|
|
||||||
]
|
|
||||||
|
|
||||||
[dependencies.iced_runtime]
|
|
||||||
path = "./iced/runtime"
|
|
||||||
|
|
||||||
[dependencies.iced_renderer]
|
|
||||||
path = "./iced/renderer"
|
|
||||||
|
|
||||||
[dependencies.iced_core]
|
|
||||||
path = "./iced/core"
|
|
||||||
features = ["serde"]
|
|
||||||
|
|
||||||
[dependencies.iced_widget]
|
|
||||||
path = "./iced/widget"
|
|
||||||
features = ["canvas"]
|
|
||||||
|
|
||||||
[dependencies.iced_futures]
|
|
||||||
path = "./iced/futures"
|
|
||||||
|
|
||||||
[dependencies.iced_accessibility]
|
|
||||||
path = "./iced/accessibility"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.iced_tiny_skia]
|
|
||||||
path = "./iced/tiny_skia"
|
|
||||||
|
|
||||||
[dependencies.iced_winit]
|
|
||||||
path = "./iced/winit"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.iced_wgpu]
|
|
||||||
path = "./iced/wgpu"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.cosmic-panel-config]
|
|
||||||
git = "https://github.com/pop-os/cosmic-panel"
|
|
||||||
# path = "../cosmic-panel/cosmic-panel-config"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.ron]
|
|
||||||
version = "0.12"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[workspace]
|
|
||||||
members = [
|
|
||||||
"cosmic-config",
|
|
||||||
"cosmic-config-derive",
|
|
||||||
"cosmic-theme",
|
|
||||||
"examples/*",
|
|
||||||
]
|
|
||||||
exclude = ["iced"]
|
|
||||||
|
|
||||||
[workspace.dependencies]
|
|
||||||
dirs = "6.0.0"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
tempfile = "3.27.0"
|
|
||||||
373
LICENSE
373
LICENSE
|
|
@ -1,373 +0,0 @@
|
||||||
Mozilla Public License Version 2.0
|
|
||||||
==================================
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
--------------
|
|
||||||
|
|
||||||
1.1. "Contributor"
|
|
||||||
means each individual or legal entity that creates, contributes to
|
|
||||||
the creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. "Contributor Version"
|
|
||||||
means the combination of the Contributions of others (if any) used
|
|
||||||
by a Contributor and that particular Contributor's Contribution.
|
|
||||||
|
|
||||||
1.3. "Contribution"
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. "Covered Software"
|
|
||||||
means Source Code Form to which the initial Contributor has attached
|
|
||||||
the notice in Exhibit A, the Executable Form of such Source Code
|
|
||||||
Form, and Modifications of such Source Code Form, in each case
|
|
||||||
including portions thereof.
|
|
||||||
|
|
||||||
1.5. "Incompatible With Secondary Licenses"
|
|
||||||
means
|
|
||||||
|
|
||||||
(a) that the initial Contributor has attached the notice described
|
|
||||||
in Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
(b) that the Covered Software was made available under the terms of
|
|
||||||
version 1.1 or earlier of the License, but not also under the
|
|
||||||
terms of a Secondary License.
|
|
||||||
|
|
||||||
1.6. "Executable Form"
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. "Larger Work"
|
|
||||||
means a work that combines Covered Software with other material, in
|
|
||||||
a separate file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. "License"
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. "Licensable"
|
|
||||||
means having the right to grant, to the maximum extent possible,
|
|
||||||
whether at the time of the initial grant or subsequently, any and
|
|
||||||
all of the rights conveyed by this License.
|
|
||||||
|
|
||||||
1.10. "Modifications"
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
(a) any file in Source Code Form that results from an addition to,
|
|
||||||
deletion from, or modification of the contents of Covered
|
|
||||||
Software; or
|
|
||||||
|
|
||||||
(b) any new file in Source Code Form that contains any Covered
|
|
||||||
Software.
|
|
||||||
|
|
||||||
1.11. "Patent Claims" of a Contributor
|
|
||||||
means any patent claim(s), including without limitation, method,
|
|
||||||
process, and apparatus claims, in any patent Licensable by such
|
|
||||||
Contributor that would be infringed, but for the grant of the
|
|
||||||
License, by the making, using, selling, offering for sale, having
|
|
||||||
made, import, or transfer of either its Contributions or its
|
|
||||||
Contributor Version.
|
|
||||||
|
|
||||||
1.12. "Secondary License"
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU
|
|
||||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
|
||||||
Public License, Version 3.0, or any later versions of those
|
|
||||||
licenses.
|
|
||||||
|
|
||||||
1.13. "Source Code Form"
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. "You" (or "Your")
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, "You" includes any entity that
|
|
||||||
controls, is controlled by, or is under common control with You. For
|
|
||||||
purposes of this definition, "control" means (a) the power, direct
|
|
||||||
or indirect, to cause the direction or management of such entity,
|
|
||||||
whether by contract or otherwise, or (b) ownership of more than
|
|
||||||
fifty percent (50%) of the outstanding shares or beneficial
|
|
||||||
ownership of such entity.
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
(a) under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or
|
|
||||||
as part of a Larger Work; and
|
|
||||||
|
|
||||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
|
||||||
for sale, have made, import, and otherwise transfer either its
|
|
||||||
Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution
|
|
||||||
become effective for each Contribution on the date the Contributor first
|
|
||||||
distributes such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under
|
|
||||||
this License. No additional rights or licenses will be implied from the
|
|
||||||
distribution or licensing of Covered Software under this License.
|
|
||||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
|
||||||
Contributor:
|
|
||||||
|
|
||||||
(a) for any code that a Contributor has removed from Covered Software;
|
|
||||||
or
|
|
||||||
|
|
||||||
(b) for infringements caused by: (i) Your and any other third party's
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
|
||||||
its Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks,
|
|
||||||
or logos of any Contributor (except as may be necessary to comply with
|
|
||||||
the notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this
|
|
||||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
|
||||||
permitted under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its
|
|
||||||
Contributions are its original creation(s) or it has sufficient rights
|
|
||||||
to grant the rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under
|
|
||||||
applicable copyright doctrines of fair use, fair dealing, or other
|
|
||||||
equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
|
||||||
in Section 2.1.
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under
|
|
||||||
the terms of this License. You must inform recipients that the Source
|
|
||||||
Code Form of the Covered Software is governed by the terms of this
|
|
||||||
License, and how they can obtain a copy of this License. You may not
|
|
||||||
attempt to alter or restrict the recipients' rights in the Source Code
|
|
||||||
Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
(a) such Covered Software must also be made available in Source Code
|
|
||||||
Form, as described in Section 3.1, and You must inform recipients of
|
|
||||||
the Executable Form how they can obtain a copy of such Source Code
|
|
||||||
Form by reasonable means in a timely manner, at a charge no more
|
|
||||||
than the cost of distribution to the recipient; and
|
|
||||||
|
|
||||||
(b) You may distribute such Executable Form under the terms of this
|
|
||||||
License, or sublicense it under different terms, provided that the
|
|
||||||
license for the Executable Form does not attempt to limit or alter
|
|
||||||
the recipients' rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for
|
|
||||||
the Covered Software. If the Larger Work is a combination of Covered
|
|
||||||
Software with a work governed by one or more Secondary Licenses, and the
|
|
||||||
Covered Software is not Incompatible With Secondary Licenses, this
|
|
||||||
License permits You to additionally distribute such Covered Software
|
|
||||||
under the terms of such Secondary License(s), so that the recipient of
|
|
||||||
the Larger Work may, at their option, further distribute the Covered
|
|
||||||
Software under the terms of either this License or such Secondary
|
|
||||||
License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices
|
|
||||||
(including copyright notices, patent notices, disclaimers of warranty,
|
|
||||||
or limitations of liability) contained within the Source Code Form of
|
|
||||||
the Covered Software, except that You may alter any license notices to
|
|
||||||
the extent required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on
|
|
||||||
behalf of any Contributor. You must make it absolutely clear that any
|
|
||||||
such warranty, support, indemnity, or liability obligation is offered by
|
|
||||||
You alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
---------------------------------------------------
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this
|
|
||||||
License with respect to some or all of the Covered Software due to
|
|
||||||
statute, judicial order, or regulation then You must: (a) comply with
|
|
||||||
the terms of this License to the maximum extent possible; and (b)
|
|
||||||
describe the limitations and the code they affect. Such description must
|
|
||||||
be placed in a text file included with all distributions of the Covered
|
|
||||||
Software under this License. Except to the extent prohibited by statute
|
|
||||||
or regulation, such description must be sufficiently detailed for a
|
|
||||||
recipient of ordinary skill to be able to understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
--------------
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically
|
|
||||||
if You fail to comply with any of its terms. However, if You become
|
|
||||||
compliant, then the rights granted under this License from a particular
|
|
||||||
Contributor are reinstated (a) provisionally, unless and until such
|
|
||||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
|
||||||
ongoing basis, if such Contributor fails to notify You of the
|
|
||||||
non-compliance by some reasonable means prior to 60 days after You have
|
|
||||||
come back into compliance. Moreover, Your grants from a particular
|
|
||||||
Contributor are reinstated on an ongoing basis if such Contributor
|
|
||||||
notifies You of the non-compliance by some reasonable means, this is the
|
|
||||||
first time You have received notice of non-compliance with this License
|
|
||||||
from such Contributor, and You become compliant prior to 30 days after
|
|
||||||
Your receipt of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions,
|
|
||||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
|
||||||
directly or indirectly infringes any patent, then the rights granted to
|
|
||||||
You by any and all Contributors for the Covered Software under Section
|
|
||||||
2.1 of this License shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
|
||||||
end user license agreements (excluding distributors and resellers) which
|
|
||||||
have been validly granted by You or Your distributors under this License
|
|
||||||
prior to termination shall survive termination.
|
|
||||||
|
|
||||||
************************************************************************
|
|
||||||
* *
|
|
||||||
* 6. Disclaimer of Warranty *
|
|
||||||
* ------------------------- *
|
|
||||||
* *
|
|
||||||
* Covered Software is provided under this License on an "as is" *
|
|
||||||
* basis, without warranty of any kind, either expressed, implied, or *
|
|
||||||
* statutory, including, without limitation, warranties that the *
|
|
||||||
* Covered Software is free of defects, merchantable, fit for a *
|
|
||||||
* particular purpose or non-infringing. The entire risk as to the *
|
|
||||||
* quality and performance of the Covered Software is with You. *
|
|
||||||
* Should any Covered Software prove defective in any respect, You *
|
|
||||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
|
||||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
|
||||||
* essential part of this License. No use of any Covered Software is *
|
|
||||||
* authorized under this License except under this disclaimer. *
|
|
||||||
* *
|
|
||||||
************************************************************************
|
|
||||||
|
|
||||||
************************************************************************
|
|
||||||
* *
|
|
||||||
* 7. Limitation of Liability *
|
|
||||||
* -------------------------- *
|
|
||||||
* *
|
|
||||||
* Under no circumstances and under no legal theory, whether tort *
|
|
||||||
* (including negligence), contract, or otherwise, shall any *
|
|
||||||
* Contributor, or anyone who distributes Covered Software as *
|
|
||||||
* permitted above, be liable to You for any direct, indirect, *
|
|
||||||
* special, incidental, or consequential damages of any character *
|
|
||||||
* including, without limitation, damages for lost profits, loss of *
|
|
||||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
|
||||||
* and all other commercial damages or losses, even if such party *
|
|
||||||
* shall have been informed of the possibility of such damages. This *
|
|
||||||
* limitation of liability shall not apply to liability for death or *
|
|
||||||
* personal injury resulting from such party's negligence to the *
|
|
||||||
* extent applicable law prohibits such limitation. Some *
|
|
||||||
* jurisdictions do not allow the exclusion or limitation of *
|
|
||||||
* incidental or consequential damages, so this exclusion and *
|
|
||||||
* limitation may not apply to You. *
|
|
||||||
* *
|
|
||||||
************************************************************************
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the
|
|
||||||
courts of a jurisdiction where the defendant maintains its principal
|
|
||||||
place of business and such litigation shall be governed by laws of that
|
|
||||||
jurisdiction, without reference to its conflict-of-law provisions.
|
|
||||||
Nothing in this Section shall prevent a party's ability to bring
|
|
||||||
cross-claims or counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
----------------
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject
|
|
||||||
matter hereof. If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent
|
|
||||||
necessary to make it enforceable. Any law or regulation which provides
|
|
||||||
that the language of a contract shall be construed against the drafter
|
|
||||||
shall not be used to construe this License against a Contributor.
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version
|
|
||||||
of the License under which You originally received the Covered Software,
|
|
||||||
or under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a
|
|
||||||
modified version of this License if you rename the license and remove
|
|
||||||
any references to the name of the license steward (except to note that
|
|
||||||
such modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
|
||||||
Licenses
|
|
||||||
|
|
||||||
If You choose to distribute Source Code Form that is Incompatible With
|
|
||||||
Secondary Licenses under the terms of this version of the License, the
|
|
||||||
notice described in Exhibit B of this License must be attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular
|
|
||||||
file, then You may include the notice in a location (such as a LICENSE
|
|
||||||
file in a relevant directory) where a recipient would be likely to look
|
|
||||||
for such a notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
|
||||||
defined by the Mozilla Public License, v. 2.0.
|
|
||||||
84
README.md
84
README.md
|
|
@ -1,84 +0,0 @@
|
||||||
# LIBCOSMIC
|
|
||||||
|
|
||||||
A platform toolkit based on iced for creating applets and applications for the COSMIC™ desktop.
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
- [API Documentation](https://pop-os.github.io/libcosmic/cosmic/): Automatically generated from this repository via `cargo doc`
|
|
||||||
- [libcosmic Book](https://pop-os.github.io/libcosmic-book/): A reference for learning libcosmic
|
|
||||||
|
|
||||||
## Templates
|
|
||||||
|
|
||||||
- https://github.com/pop-os/cosmic-app-template: Application project template
|
|
||||||
- https://github.com/pop-os/cosmic-applet-template: Panel applet project template
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
While libcosmic is written entirely in Rust, some of its dependencies may require shared system library headers to be installed. On Pop!_OS, the following dependencies are all that's necessary to compile a typical COSMIC project:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo apt install cargo cmake just libexpat1-dev libfontconfig-dev libfreetype-dev libxkbcommon-dev pkgconf
|
|
||||||
```
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
Some examples are included in the [examples](./examples) directory to to kickstart your
|
|
||||||
COSMIC adventure. To run them, you need to clone the repository with the following commands:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone --recurse-submodules https://github.com/pop-os/libcosmic
|
|
||||||
cd libcosmic
|
|
||||||
```
|
|
||||||
|
|
||||||
If you have already cloned the repository, run these to sync with the latest updates:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git fetch origin
|
|
||||||
git checkout master
|
|
||||||
git reset --hard origin/master
|
|
||||||
```
|
|
||||||
|
|
||||||
The examples may then be run by their cargo project names, such as `just run application`.
|
|
||||||
|
|
||||||
## Cargo Features
|
|
||||||
|
|
||||||
Available cargo features to choose from:
|
|
||||||
|
|
||||||
- `a11y`: Experimental accessibility support.
|
|
||||||
- `animated-image`: Enables animated images from the image crate.
|
|
||||||
- `debug`: Enables addtional debugging features.
|
|
||||||
- `smol`: Uses smol as the preferred async runtime.
|
|
||||||
- Conflicts with `tokio`
|
|
||||||
- `tokio`: Uses tokio as the preferred async runtime.
|
|
||||||
- If unset, the default executor defined by iced will be used.
|
|
||||||
- Conflicts with `smol`
|
|
||||||
- `wayland`: Wayland-compatible client windows.
|
|
||||||
- Conflicts with `winit`
|
|
||||||
- `winit`: Cross-platform and X11 client window support
|
|
||||||
- Conflicts with `wayland`
|
|
||||||
- `wgpu`: GPU accelerated rendering with WGPU.
|
|
||||||
- By default, softbuffer is used for software rendering.
|
|
||||||
- `xdg-portal`: Enables XDG portal dialog integrations.
|
|
||||||
|
|
||||||
### Project Showcase
|
|
||||||
|
|
||||||
- [COSMIC App Library](https://github.com/pop-os/cosmic-applibrary)
|
|
||||||
- [COSMIC Applets](https://github.com/pop-os/cosmic-applets)
|
|
||||||
- [COSMIC Launcher](https://github.com/pop-os/cosmic-launcher)
|
|
||||||
- [COSMIC Notifications](https://github.com/pop-os/cosmic-notifications)
|
|
||||||
- [COSMIC Panel](https://github.com/pop-os/cosmic-panel)
|
|
||||||
- [COSMIC Text Editor](https://github.com/pop-os/cosmic-text-editor)
|
|
||||||
- [COSMIC Settings](https://github.com/pop-os/cosmic-settings)
|
|
||||||
|
|
||||||
## Licence
|
|
||||||
|
|
||||||
Licensed under the [Mozilla Public License 2.0](https://choosealicense.com/licenses/mpl-2.0).
|
|
||||||
|
|
||||||
## Contact
|
|
||||||
|
|
||||||
- [Mattermost](https://chat.pop-os.org/)
|
|
||||||
- [Lemmy](https://lemmy.world/c/pop_os)
|
|
||||||
- [Mastodon](https://fosstodon.org/@pop_os_official)
|
|
||||||
- [Reddit](https://www.reddit.com/r/pop_os/)
|
|
||||||
- [Twitter](https://twitter.com/pop_os_official)
|
|
||||||
- [Instagram](https://www.instagram.com/pop_os_official)
|
|
||||||
63
build.rs
63
build.rs
|
|
@ -1,63 +0,0 @@
|
||||||
use std::env;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("cargo::rerun-if-changed=build.rs");
|
|
||||||
|
|
||||||
if env::var_os("CARGO_CFG_UNIX").is_none()
|
|
||||||
|| env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("macos")
|
|
||||||
{
|
|
||||||
generate_bundled_icons();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_bundled_icons() {
|
|
||||||
println!("cargo::rerun-if-changed=cosmic-icons");
|
|
||||||
|
|
||||||
let manifest_dir = std::path::Path::new(std::env!("CARGO_MANIFEST_DIR"));
|
|
||||||
let icon_paths = [
|
|
||||||
"cosmic-icons/freedesktop/scalable",
|
|
||||||
"cosmic-icons/extra/scalable",
|
|
||||||
];
|
|
||||||
|
|
||||||
let key_value_assignments = icon_paths
|
|
||||||
.into_iter()
|
|
||||||
.map(|path| manifest_dir.join(path))
|
|
||||||
.inspect(|icon_path| assert!(icon_path.exists(), "path = {icon_path:?}"))
|
|
||||||
.map(|icon_path| std::fs::read_dir(icon_path).unwrap())
|
|
||||||
.flat_map(|dir| {
|
|
||||||
dir.flat_map(|entry| entry.unwrap().path().read_dir().unwrap())
|
|
||||||
.map(|entry| {
|
|
||||||
let entry = entry.unwrap();
|
|
||||||
let path = entry.path().canonicalize().unwrap();
|
|
||||||
let file_name = path.file_stem().unwrap().to_str().unwrap().to_owned();
|
|
||||||
let path = path.into_os_string().into_string().unwrap();
|
|
||||||
(file_name, path)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.fold(
|
|
||||||
std::collections::BTreeMap::new(),
|
|
||||||
|mut set, (name, path)| {
|
|
||||||
set.insert(name, path);
|
|
||||||
set
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.into_iter()
|
|
||||||
.fold(String::new(), |mut output, (name, path)| {
|
|
||||||
// This changes the escape character to the one used by Windows.
|
|
||||||
#[cfg(windows)]
|
|
||||||
let path = path.replace("\\", "/");
|
|
||||||
output.push_str(&format!(" \"{name}\" => include_bytes!(\"{path}\"),\n"));
|
|
||||||
output
|
|
||||||
});
|
|
||||||
|
|
||||||
let code = [
|
|
||||||
"static ICONS: phf::Map<&'static str, &'static [u8]> = phf::phf_map!(\n",
|
|
||||||
&key_value_assignments,
|
|
||||||
");",
|
|
||||||
]
|
|
||||||
.concat();
|
|
||||||
|
|
||||||
let out_dir = std::env::var_os("OUT_DIR").unwrap();
|
|
||||||
let out_file = std::path::Path::new(&out_dir).join("bundled_icons.rs");
|
|
||||||
std::fs::write(&out_file, &code).unwrap();
|
|
||||||
}
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
[build]
|
|
||||||
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "cosmic-config-derive"
|
|
||||||
version = "1.0.0"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
[lib]
|
|
||||||
proc-macro = true
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
syn = "2.0"
|
|
||||||
quote = "1.0"
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
use proc_macro::TokenStream;
|
|
||||||
use quote::quote;
|
|
||||||
use syn::{self};
|
|
||||||
|
|
||||||
#[proc_macro_derive(CosmicConfigEntry, attributes(version, id))]
|
|
||||||
pub fn cosmic_config_entry_derive(input: TokenStream) -> TokenStream {
|
|
||||||
// Construct a representation of Rust code as a syntax tree
|
|
||||||
// that we can manipulate
|
|
||||||
let ast = syn::parse(input).unwrap();
|
|
||||||
|
|
||||||
// Build the trait implementation
|
|
||||||
impl_cosmic_config_entry_macro(&ast)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn impl_cosmic_config_entry_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|
||||||
let attributes = &ast.attrs;
|
|
||||||
let version = attributes
|
|
||||||
.iter()
|
|
||||||
.find_map(|attr| {
|
|
||||||
if attr.path().is_ident("version") {
|
|
||||||
match attr.meta {
|
|
||||||
syn::Meta::NameValue(syn::MetaNameValue {
|
|
||||||
value:
|
|
||||||
syn::Expr::Lit(syn::ExprLit {
|
|
||||||
lit: syn::Lit::Int(ref lit_int),
|
|
||||||
..
|
|
||||||
}),
|
|
||||||
..
|
|
||||||
}) => Some(lit_int.base10_parse::<u64>().unwrap()),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.unwrap_or(0);
|
|
||||||
|
|
||||||
let name = &ast.ident;
|
|
||||||
|
|
||||||
// Get the fields of the struct
|
|
||||||
let fields = match ast.data {
|
|
||||||
syn::Data::Struct(ref data_struct) => match data_struct.fields {
|
|
||||||
syn::Fields::Named(ref fields) => &fields.named,
|
|
||||||
_ => unimplemented!("Only named fields are supported"),
|
|
||||||
},
|
|
||||||
_ => unimplemented!("Only structs are supported"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let write_each_config_field = fields.iter().map(|field| {
|
|
||||||
let field_name = &field.ident;
|
|
||||||
quote! {
|
|
||||||
cosmic_config::ConfigSet::set(&tx, stringify!(#field_name), &self.#field_name)?;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let get_each_config_field = fields.iter().map(|field| {
|
|
||||||
let field_name = &field.ident;
|
|
||||||
let field_type = &field.ty;
|
|
||||||
quote! {
|
|
||||||
match cosmic_config::ConfigGet::get::<#field_type>(config, stringify!(#field_name)) {
|
|
||||||
Ok(#field_name) => default.#field_name = #field_name,
|
|
||||||
Err(why) if matches!(why, cosmic_config::Error::NoConfigDirectory) => (),
|
|
||||||
Err(e) => errors.push(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let update_each_config_field = fields.iter().map(|field| {
|
|
||||||
let field_name = &field.ident;
|
|
||||||
let field_type = &field.ty;
|
|
||||||
quote! {
|
|
||||||
stringify!(#field_name) => {
|
|
||||||
match cosmic_config::ConfigGet::get::<#field_type>(config, stringify!(#field_name)) {
|
|
||||||
Ok(value) => {
|
|
||||||
if self.#field_name != value {
|
|
||||||
keys.push(stringify!(#field_name));
|
|
||||||
}
|
|
||||||
self.#field_name = value;
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
errors.push(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let setters = fields.iter().filter_map(|field| {
|
|
||||||
let field_name = &field.ident.as_ref()?;
|
|
||||||
let field_type = &field.ty;
|
|
||||||
let setter_name = quote::format_ident!("set_{}", field_name);
|
|
||||||
let doc = format!("Sets [`{name}::{field_name}`] and writes to [`cosmic_config::Config`] if changed");
|
|
||||||
Some(quote! {
|
|
||||||
#[doc = #doc]
|
|
||||||
///
|
|
||||||
/// Returns `Ok(true)` when the field's value has changed and was written to disk
|
|
||||||
pub fn #setter_name(&mut self, config: &cosmic_config::Config, value: #field_type) -> Result<bool, cosmic_config::Error> {
|
|
||||||
if self.#field_name != value {
|
|
||||||
self.#field_name = value;
|
|
||||||
cosmic_config::ConfigSet::set(config, stringify!(#field_name), &self.#field_name)?;
|
|
||||||
Ok(true)
|
|
||||||
} else {
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
let generate = quote! {
|
|
||||||
impl CosmicConfigEntry for #name {
|
|
||||||
const VERSION: u64 = #version;
|
|
||||||
|
|
||||||
fn write_entry(&self, config: &cosmic_config::Config) -> Result<(), cosmic_config::Error> {
|
|
||||||
let tx = config.transaction();
|
|
||||||
#(#write_each_config_field)*
|
|
||||||
tx.commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_entry(config: &cosmic_config::Config) -> Result<Self, (Vec<cosmic_config::Error>, Self)> {
|
|
||||||
let mut default = Self::default();
|
|
||||||
let mut errors = Vec::new();
|
|
||||||
|
|
||||||
#(#get_each_config_field)*
|
|
||||||
|
|
||||||
if errors.is_empty() {
|
|
||||||
Ok(default)
|
|
||||||
} else {
|
|
||||||
Err((errors, default))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_keys<T: AsRef<str>>(&mut self, config: &cosmic_config::Config, changed_keys: &[T]) -> (Vec<cosmic_config::Error>, Vec<&'static str>){
|
|
||||||
let mut keys = Vec::with_capacity(changed_keys.len());
|
|
||||||
let mut errors = Vec::new();
|
|
||||||
for key in changed_keys.iter() {
|
|
||||||
match key.as_ref() {
|
|
||||||
#(#update_each_config_field)*
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(errors, keys)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl #name {
|
|
||||||
#(#setters)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
generate.into()
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "cosmic-config"
|
|
||||||
version = "1.0.0"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["macro", "subscription"]
|
|
||||||
dbus = ["dep:zbus", "cosmic-settings-daemon", "futures-util", "subscription"]
|
|
||||||
macro = ["cosmic-config-derive"]
|
|
||||||
subscription = ["iced_futures"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
cosmic-settings-daemon = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
|
|
||||||
zbus = { version = "5.14.0", default-features = false, optional = true }
|
|
||||||
atomicwrites = { git = "https://github.com/jackpot51/rust-atomicwrites" }
|
|
||||||
calloop = { version = "0.14.4", optional = true }
|
|
||||||
notify = "8.2.0"
|
|
||||||
ron = "0.12.0"
|
|
||||||
serde = "1.0.228"
|
|
||||||
cosmic-config-derive = { path = "../cosmic-config-derive/", optional = true }
|
|
||||||
iced = { path = "../iced/", default-features = false, optional = true }
|
|
||||||
iced_futures = { path = "../iced/futures/", default-features = false, optional = true }
|
|
||||||
futures-util = { version = "0.3", optional = true }
|
|
||||||
dirs.workspace = true
|
|
||||||
tokio = { version = "1.50", optional = true, features = ["time"] }
|
|
||||||
async-std = { version = "1.13", optional = true }
|
|
||||||
tracing = "0.1"
|
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
|
||||||
xdg = "3.0"
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
|
||||||
known-folders = "1.4.2"
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
// TODO If possible, calloop could poll inotify/kqueue without a thread
|
|
||||||
|
|
||||||
use calloop::channel;
|
|
||||||
|
|
||||||
use crate::{Config, Error};
|
|
||||||
|
|
||||||
pub struct ConfigWatchSource {
|
|
||||||
channel: channel::Channel<(Config, Vec<String>)>,
|
|
||||||
_watcher: notify::RecommendedWatcher,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConfigWatchSource {
|
|
||||||
pub fn new(config: &Config) -> Result<Self, Error> {
|
|
||||||
let (sender, channel) = channel::sync_channel(32);
|
|
||||||
let _watcher = config.watch(move |config, keys| {
|
|
||||||
let _ = sender.send((config.clone(), keys.to_owned()));
|
|
||||||
})?;
|
|
||||||
Ok(Self { channel, _watcher })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl calloop::EventSource for ConfigWatchSource {
|
|
||||||
type Event = (Config, Vec<String>);
|
|
||||||
type Metadata = ();
|
|
||||||
type Ret = ();
|
|
||||||
type Error = calloop::channel::ChannelError;
|
|
||||||
|
|
||||||
fn process_events<F>(
|
|
||||||
&mut self,
|
|
||||||
readiness: calloop::Readiness,
|
|
||||||
token: calloop::Token,
|
|
||||||
mut cb: F,
|
|
||||||
) -> Result<calloop::PostAction, Self::Error>
|
|
||||||
where
|
|
||||||
F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret,
|
|
||||||
{
|
|
||||||
self.channel
|
|
||||||
.process_events(readiness, token, |event, ()| match event {
|
|
||||||
calloop::channel::Event::Msg(msg) => cb(msg, &mut ()),
|
|
||||||
calloop::channel::Event::Closed => {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register(
|
|
||||||
&mut self,
|
|
||||||
poll: &mut calloop::Poll,
|
|
||||||
token_factory: &mut calloop::TokenFactory,
|
|
||||||
) -> Result<(), calloop::Error> {
|
|
||||||
self.channel.register(poll, token_factory)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reregister(
|
|
||||||
&mut self,
|
|
||||||
poll: &mut calloop::Poll,
|
|
||||||
token_factory: &mut calloop::TokenFactory,
|
|
||||||
) -> Result<(), calloop::Error> {
|
|
||||||
self.channel.reregister(poll, token_factory)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn unregister(&mut self, poll: &mut calloop::Poll) -> Result<(), calloop::Error> {
|
|
||||||
self.channel.unregister(poll)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,262 +0,0 @@
|
||||||
use std::{any::TypeId, ops::Deref};
|
|
||||||
|
|
||||||
use crate::{CosmicConfigEntry, Update};
|
|
||||||
use cosmic_settings_daemon::{Changed, ConfigProxy, CosmicSettingsDaemonProxy};
|
|
||||||
use futures_util::SinkExt;
|
|
||||||
use iced_futures::{
|
|
||||||
Subscription,
|
|
||||||
futures::{self, StreamExt, future::pending},
|
|
||||||
stream,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub async fn settings_daemon_proxy() -> zbus::Result<CosmicSettingsDaemonProxy<'static>> {
|
|
||||||
let conn = zbus::Connection::session().await?;
|
|
||||||
CosmicSettingsDaemonProxy::new(&conn).await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Watcher {
|
|
||||||
proxy: ConfigProxy<'static>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Watcher {
|
|
||||||
type Target = ConfigProxy<'static>;
|
|
||||||
#[inline]
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.proxy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Watcher {
|
|
||||||
pub async fn new_config(
|
|
||||||
settings_daemon_proxy: &CosmicSettingsDaemonProxy<'static>,
|
|
||||||
id: &str,
|
|
||||||
version: u64,
|
|
||||||
) -> zbus::Result<Self> {
|
|
||||||
let (path, name) = settings_daemon_proxy.watch_config(id, version).await?;
|
|
||||||
ConfigProxy::builder(settings_daemon_proxy.inner().connection())
|
|
||||||
.path(path)?
|
|
||||||
.destination(name)?
|
|
||||||
.build()
|
|
||||||
.await
|
|
||||||
.map(|proxy| Self { proxy })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn new_state(
|
|
||||||
settings_daemon_proxy: &CosmicSettingsDaemonProxy<'static>,
|
|
||||||
id: &str,
|
|
||||||
version: u64,
|
|
||||||
) -> zbus::Result<Self> {
|
|
||||||
let (path, name) = settings_daemon_proxy.watch_state(id, version).await?;
|
|
||||||
ConfigProxy::builder(settings_daemon_proxy.inner().connection())
|
|
||||||
.path(path)?
|
|
||||||
.destination(name)?
|
|
||||||
.build()
|
|
||||||
.await
|
|
||||||
.map(|proxy| Self { proxy })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Wrapper(
|
|
||||||
TypeId,
|
|
||||||
CosmicSettingsDaemonProxy<'static>,
|
|
||||||
&'static str,
|
|
||||||
bool,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl std::hash::Hash for Wrapper {
|
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
||||||
self.0.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
|
||||||
pub fn watcher_subscription<T: CosmicConfigEntry + Send + Sync + Default + 'static + Clone>(
|
|
||||||
settings_daemon: CosmicSettingsDaemonProxy<'static>,
|
|
||||||
config_id: &'static str,
|
|
||||||
is_state: bool,
|
|
||||||
) -> iced_futures::Subscription<Update<T>> {
|
|
||||||
let id = std::any::TypeId::of::<T>();
|
|
||||||
Subscription::run_with(
|
|
||||||
Wrapper(id, settings_daemon, config_id, is_state),
|
|
||||||
|&Wrapper(_, ref settings_daemon, ref config_id, ref is_state)| {
|
|
||||||
let is_state = *is_state;
|
|
||||||
let config_id = *config_id;
|
|
||||||
let settings_daemon = settings_daemon.clone();
|
|
||||||
enum Change {
|
|
||||||
Changes(Changed),
|
|
||||||
OwnerChanged(bool),
|
|
||||||
}
|
|
||||||
stream::channel(
|
|
||||||
5,
|
|
||||||
move |mut tx: futures::channel::mpsc::Sender<Update<T>>| async move {
|
|
||||||
let version = T::VERSION;
|
|
||||||
|
|
||||||
let Ok(cosmic_config) = (if is_state {
|
|
||||||
crate::Config::new_state(config_id, version)
|
|
||||||
} else {
|
|
||||||
crate::Config::new(config_id, version)
|
|
||||||
}) else {
|
|
||||||
pending::<()>().await;
|
|
||||||
unreachable!();
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut attempts = 0;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let watcher = if is_state {
|
|
||||||
Watcher::new_state(&settings_daemon, config_id, version).await
|
|
||||||
} else {
|
|
||||||
Watcher::new_config(&settings_daemon, config_id, version).await
|
|
||||||
};
|
|
||||||
let Ok(watcher) = watcher else {
|
|
||||||
tracing::error!("Failed to create watcher for {config_id}");
|
|
||||||
|
|
||||||
#[cfg(feature = "tokio")]
|
|
||||||
::tokio::time::sleep(::tokio::time::Duration::from_secs(
|
|
||||||
2_u64.pow(attempts),
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
#[cfg(feature = "async-std")]
|
|
||||||
async_std::task::sleep(std::time::Duration::from_secs(
|
|
||||||
2_u64.pow(attempts),
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
#[cfg(not(any(feature = "tokio", feature = "async-std")))]
|
|
||||||
{
|
|
||||||
pending::<()>().await;
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
attempts += 1;
|
|
||||||
// The settings daemon has exited
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let Ok(changes) = watcher.receive_changed().await else {
|
|
||||||
tracing::error!("Failed to listen for changes for {config_id}");
|
|
||||||
|
|
||||||
#[cfg(feature = "tokio")]
|
|
||||||
::tokio::time::sleep(::tokio::time::Duration::from_secs(
|
|
||||||
2_u64.pow(attempts),
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
#[cfg(feature = "async-std")]
|
|
||||||
async_std::task::sleep(std::time::Duration::from_secs(
|
|
||||||
2_u64.pow(attempts),
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
#[cfg(not(any(feature = "tokio", feature = "async-std")))]
|
|
||||||
{
|
|
||||||
pending::<()>().await;
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
attempts += 1;
|
|
||||||
// The settings daemon has exited
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut changes = changes.map(Change::Changes).fuse();
|
|
||||||
|
|
||||||
let Ok(owner_changed) = watcher.inner().receive_owner_changed().await
|
|
||||||
else {
|
|
||||||
tracing::error!("Failed to listen for owner changes for {config_id}");
|
|
||||||
#[cfg(feature = "tokio")]
|
|
||||||
::tokio::time::sleep(::tokio::time::Duration::from_secs(
|
|
||||||
2_u64.pow(attempts),
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
#[cfg(feature = "async-std")]
|
|
||||||
async_std::task::sleep(std::time::Duration::from_secs(
|
|
||||||
2_u64.pow(attempts),
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
#[cfg(not(any(feature = "tokio", feature = "async-std")))]
|
|
||||||
{
|
|
||||||
pending::<()>().await;
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
attempts += 1;
|
|
||||||
// The settings daemon has exited
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let mut owner_changed = owner_changed
|
|
||||||
.map(|c| Change::OwnerChanged(c.is_some()))
|
|
||||||
.fuse();
|
|
||||||
|
|
||||||
// update now, just in case we missed changes while setting up stream
|
|
||||||
let mut config = match T::get_entry(&cosmic_config) {
|
|
||||||
Ok(config) => config,
|
|
||||||
Err((errors, default)) => {
|
|
||||||
for why in &errors {
|
|
||||||
if why.is_err() {
|
|
||||||
if let crate::Error::GetKey(_, err) = &why {
|
|
||||||
if err.kind() == std::io::ErrorKind::NotFound {
|
|
||||||
// No system default config installed; don't error
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tracing::error!("error getting config: {config_id} {why}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(err) = tx
|
|
||||||
.send(Update {
|
|
||||||
errors: Vec::new(),
|
|
||||||
keys: Vec::new(),
|
|
||||||
config: config.clone(),
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
tracing::error!("Failed to send config: {err}");
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let change: Changed = futures::select! {
|
|
||||||
c = changes.next() => {
|
|
||||||
let Some(Change::Changes(c)) = c else {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
c
|
|
||||||
}
|
|
||||||
c = owner_changed.next() => {
|
|
||||||
let Some(Change::OwnerChanged(cont)) = c else {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
if cont {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
// The settings daemon has exited
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Reset the attempts counter if we received a change
|
|
||||||
attempts = 0;
|
|
||||||
let Ok(args) = change.args() else {
|
|
||||||
// The settings daemon has exited
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
let (errors, keys) = config.update_keys(&cosmic_config, &[args.key]);
|
|
||||||
if !keys.is_empty() {
|
|
||||||
if let Err(err) = tx
|
|
||||||
.send(Update {
|
|
||||||
errors,
|
|
||||||
keys,
|
|
||||||
config: config.clone(),
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
tracing::error!("Failed to send config update: {err}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,459 +0,0 @@
|
||||||
//! Integrations for cosmic-config — the cosmic configuration system.
|
|
||||||
|
|
||||||
use notify::{
|
|
||||||
RecommendedWatcher, Watcher,
|
|
||||||
event::{EventKind, ModifyKind, RenameMode},
|
|
||||||
};
|
|
||||||
use serde::{Serialize, de::DeserializeOwned};
|
|
||||||
use std::{
|
|
||||||
env, fmt, fs,
|
|
||||||
io::Write,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
sync::Mutex,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Get the config directory, with Flatpak sandbox support.
|
|
||||||
/// In Flatpak, HOST_XDG_CONFIG_HOME points to the real user config directory,
|
|
||||||
/// allowing sandboxed apps to read host config files.
|
|
||||||
fn get_config_dir() -> Option<PathBuf> {
|
|
||||||
// Check if we're running in Flatpak
|
|
||||||
if let Some(flatpak_id) = env::var_os("FLATPAK_ID") {
|
|
||||||
tracing::debug!("Running in Flatpak: {:?}", flatpak_id);
|
|
||||||
// Try HOST_XDG_CONFIG_HOME first (requires --filesystem=xdg-config permission)
|
|
||||||
if let Some(host_config) = env::var_os("HOST_XDG_CONFIG_HOME") {
|
|
||||||
tracing::debug!("Using HOST_XDG_CONFIG_HOME: {:?}", host_config);
|
|
||||||
return Some(PathBuf::from(host_config));
|
|
||||||
}
|
|
||||||
// Fallback: try to construct from HOME (which points to real home in Flatpak)
|
|
||||||
if let Some(home) = env::var_os("HOME") {
|
|
||||||
let config_path = PathBuf::from(&home).join(".config");
|
|
||||||
tracing::debug!("Using HOME fallback for config: {:?}", config_path);
|
|
||||||
return Some(config_path);
|
|
||||||
}
|
|
||||||
tracing::warn!("Flatpak detected but no config directory found");
|
|
||||||
}
|
|
||||||
// Not in Flatpak or no host config available, use standard dirs
|
|
||||||
let config_dir = dirs::config_dir();
|
|
||||||
tracing::debug!("Using standard config dir: {:?}", config_dir);
|
|
||||||
config_dir
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the state directory, with Flatpak sandbox support.
|
|
||||||
fn get_state_dir() -> Option<PathBuf> {
|
|
||||||
// Check if we're running in Flatpak
|
|
||||||
if env::var_os("FLATPAK_ID").is_some() {
|
|
||||||
// Try HOST_XDG_STATE_HOME first
|
|
||||||
if let Some(host_state) = env::var_os("HOST_XDG_STATE_HOME") {
|
|
||||||
return Some(PathBuf::from(host_state));
|
|
||||||
}
|
|
||||||
// Fallback: try to construct from HOME
|
|
||||||
if let Some(home) = env::var_os("HOME") {
|
|
||||||
return Some(PathBuf::from(home).join(".local").join("state"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dirs::state_dir()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "subscription")]
|
|
||||||
mod subscription;
|
|
||||||
#[cfg(feature = "subscription")]
|
|
||||||
pub use subscription::*;
|
|
||||||
|
|
||||||
#[cfg(all(feature = "dbus", feature = "subscription"))]
|
|
||||||
pub mod dbus;
|
|
||||||
|
|
||||||
#[cfg(feature = "macro")]
|
|
||||||
pub use cosmic_config_derive;
|
|
||||||
|
|
||||||
#[cfg(feature = "calloop")]
|
|
||||||
pub mod calloop;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Error {
|
|
||||||
AtomicWrites(atomicwrites::Error<std::io::Error>),
|
|
||||||
InvalidName(String),
|
|
||||||
Io(std::io::Error),
|
|
||||||
NoConfigDirectory,
|
|
||||||
Notify(notify::Error),
|
|
||||||
NotFound,
|
|
||||||
Ron(ron::Error),
|
|
||||||
RonSpanned(ron::error::SpannedError),
|
|
||||||
GetKey(String, std::io::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
|
||||||
#[cold]
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::AtomicWrites(err) => err.fmt(f),
|
|
||||||
Self::InvalidName(name) => write!(f, "invalid config name '{}'", name),
|
|
||||||
Self::Io(err) => err.fmt(f),
|
|
||||||
Self::NoConfigDirectory => write!(f, "cosmic config directory not found"),
|
|
||||||
Self::Notify(err) => err.fmt(f),
|
|
||||||
Self::NotFound => write!(f, "cosmic config key not configured"),
|
|
||||||
Self::Ron(err) => err.fmt(f),
|
|
||||||
Self::RonSpanned(err) => err.fmt(f),
|
|
||||||
Self::GetKey(key, err) => write!(f, "failed to get key '{}': {}", key, err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for Error {}
|
|
||||||
|
|
||||||
impl Error {
|
|
||||||
/// Whether the reason for the missing config is caused by an error.
|
|
||||||
///
|
|
||||||
/// Useful for determining if it is appropriate to log as an error.
|
|
||||||
#[inline]
|
|
||||||
pub fn is_err(&self) -> bool {
|
|
||||||
!matches!(self, Self::NoConfigDirectory | Self::NotFound)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<atomicwrites::Error<std::io::Error>> for Error {
|
|
||||||
fn from(f: atomicwrites::Error<std::io::Error>) -> Self {
|
|
||||||
Self::AtomicWrites(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<std::io::Error> for Error {
|
|
||||||
fn from(f: std::io::Error) -> Self {
|
|
||||||
Self::Io(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<notify::Error> for Error {
|
|
||||||
fn from(f: notify::Error) -> Self {
|
|
||||||
Self::Notify(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ron::Error> for Error {
|
|
||||||
fn from(f: ron::Error) -> Self {
|
|
||||||
Self::Ron(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ron::error::SpannedError> for Error {
|
|
||||||
fn from(f: ron::error::SpannedError) -> Self {
|
|
||||||
Self::RonSpanned(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ConfigGet {
|
|
||||||
/// Get a configuration value
|
|
||||||
///
|
|
||||||
/// Fallback to the system default if a local user override is not defined.
|
|
||||||
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
|
|
||||||
|
|
||||||
/// Get a locally-defined configuration value from the user's local config.
|
|
||||||
fn get_local<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
|
|
||||||
|
|
||||||
/// Get the system-defined default configuration value.
|
|
||||||
fn get_system_default<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ConfigSet {
|
|
||||||
/// Set a configuration value
|
|
||||||
fn set<T: Serialize>(&self, key: &str, value: T) -> Result<(), Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Config {
|
|
||||||
system_path: Option<PathBuf>,
|
|
||||||
user_path: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check that the name is relative and doesn't contain . or ..
|
|
||||||
fn sanitize_name(name: &str) -> Result<&Path, Error> {
|
|
||||||
let path = Path::new(name);
|
|
||||||
if path
|
|
||||||
.components()
|
|
||||||
.all(|x| matches!(x, std::path::Component::Normal(_)))
|
|
||||||
{
|
|
||||||
Ok(path)
|
|
||||||
} else {
|
|
||||||
Err(Error::InvalidName(name.to_owned()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config {
|
|
||||||
/// Get a system config for the given name and config version
|
|
||||||
pub fn system(name: &str, version: u64) -> Result<Self, Error> {
|
|
||||||
let path = sanitize_name(name)?.join(format!("v{version}"));
|
|
||||||
#[cfg(unix)]
|
|
||||||
let system_path = xdg::BaseDirectories::with_prefix("cosmic").find_data_file(path);
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
let system_path =
|
|
||||||
known_folders::get_known_folder_path(known_folders::KnownFolder::ProgramFilesCommon)
|
|
||||||
.map(|x| x.join("COSMIC").join(&path));
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
system_path,
|
|
||||||
user_path: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get config for the given application name and config version
|
|
||||||
// Use folder at XDG config/name for config storage, return Config if successful
|
|
||||||
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
|
||||||
pub fn new(name: &str, version: u64) -> Result<Self, Error> {
|
|
||||||
// Look for [name]/v[version]
|
|
||||||
let path = sanitize_name(name)?.join(format!("v{}", version));
|
|
||||||
|
|
||||||
// Search data file, which provides default (e.g. /usr/share)
|
|
||||||
#[cfg(unix)]
|
|
||||||
let system_path = xdg::BaseDirectories::with_prefix("cosmic").find_data_file(&path);
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
let system_path =
|
|
||||||
known_folders::get_known_folder_path(known_folders::KnownFolder::ProgramFilesCommon)
|
|
||||||
.map(|x| x.join("COSMIC").join(&path));
|
|
||||||
|
|
||||||
// Get libcosmic user configuration directory
|
|
||||||
let mut user_path = get_config_dir().ok_or(Error::NoConfigDirectory)?;
|
|
||||||
user_path.push("cosmic");
|
|
||||||
user_path.push(path);
|
|
||||||
|
|
||||||
// Create new configuration directory if not found.
|
|
||||||
fs::create_dir_all(&user_path)?;
|
|
||||||
|
|
||||||
// Return Config
|
|
||||||
Ok(Self {
|
|
||||||
system_path,
|
|
||||||
user_path: Some(user_path),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get config for the given application name and config version and custom path.
|
|
||||||
pub fn with_custom_path(name: &str, version: u64, custom_path: PathBuf) -> Result<Self, Error> {
|
|
||||||
// Look for [name]/v[version]
|
|
||||||
let path = sanitize_name(name)?.join(format!("v{version}"));
|
|
||||||
|
|
||||||
let mut user_path = custom_path;
|
|
||||||
user_path.push("cosmic");
|
|
||||||
user_path.push(path);
|
|
||||||
// Create new configuration directory if not found.
|
|
||||||
fs::create_dir_all(&user_path)?;
|
|
||||||
|
|
||||||
// Return Config
|
|
||||||
Ok(Self {
|
|
||||||
system_path: None,
|
|
||||||
user_path: Some(user_path),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get state for the given application name and config version. State is meant to be used to
|
|
||||||
/// store items that may need to be exposed to other programs but will change regularly without
|
|
||||||
/// user action
|
|
||||||
// Use folder at XDG config/name for config storage, return Config if successful
|
|
||||||
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
|
||||||
pub fn new_state(name: &str, version: u64) -> Result<Self, Error> {
|
|
||||||
// Look for [name]/v[version]
|
|
||||||
let path = sanitize_name(name)?.join(format!("v{}", version));
|
|
||||||
|
|
||||||
// Get libcosmic user state directory
|
|
||||||
let mut user_path = get_state_dir().ok_or(Error::NoConfigDirectory)?;
|
|
||||||
user_path.push("cosmic");
|
|
||||||
user_path.push(path);
|
|
||||||
// Create new state directory if not found.
|
|
||||||
fs::create_dir_all(&user_path)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
system_path: None,
|
|
||||||
user_path: Some(user_path),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a transaction (to set multiple configs at the same time)
|
|
||||||
#[inline]
|
|
||||||
pub fn transaction(&self) -> ConfigTransaction<'_> {
|
|
||||||
ConfigTransaction {
|
|
||||||
config: self,
|
|
||||||
updates: Mutex::new(Vec::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch keys for changes, will be triggered once per transaction
|
|
||||||
// This may end up being an mpsc channel instead of a function
|
|
||||||
// See EventHandler in the notify crate: https://docs.rs/notify/latest/notify/trait.EventHandler.html
|
|
||||||
// Having a callback allows for any application abstraction to be used
|
|
||||||
pub fn watch<F>(&self, f: F) -> Result<RecommendedWatcher, Error>
|
|
||||||
// Argument is an array of all keys that changed in that specific transaction
|
|
||||||
//TODO: simplify F requirements
|
|
||||||
where
|
|
||||||
F: Fn(&Self, &[String]) + Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
let watch_config = self.clone();
|
|
||||||
let Some(user_path) = self.user_path.as_ref() else {
|
|
||||||
return Err(Error::NoConfigDirectory);
|
|
||||||
};
|
|
||||||
let user_path_clone = user_path.clone();
|
|
||||||
let mut watcher =
|
|
||||||
notify::recommended_watcher(move |event_res: Result<notify::Event, notify::Error>| {
|
|
||||||
match event_res {
|
|
||||||
Ok(event) => {
|
|
||||||
match &event.kind {
|
|
||||||
EventKind::Access(_)
|
|
||||||
| EventKind::Modify(ModifyKind::Metadata(_))
|
|
||||||
| EventKind::Modify(ModifyKind::Name(RenameMode::Both)) => {
|
|
||||||
// Data not mutated
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut keys = Vec::new();
|
|
||||||
for path in &event.paths {
|
|
||||||
match path.strip_prefix(&user_path_clone) {
|
|
||||||
Ok(key_path) => {
|
|
||||||
if let Some(key) = key_path.to_str() {
|
|
||||||
// Skip any .atomicwrite temporary files
|
|
||||||
if key.starts_with(".atomicwrite") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
keys.push(key.to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_err) => {
|
|
||||||
//TODO: handle errors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !keys.is_empty() {
|
|
||||||
f(&watch_config, &keys);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_err) => {
|
|
||||||
//TODO: handle errors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
watcher.watch(user_path, notify::RecursiveMode::Recursive)?;
|
|
||||||
Ok(watcher)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_path(&self, key: &str) -> Result<PathBuf, Error> {
|
|
||||||
let Some(system_path) = self.system_path.as_ref() else {
|
|
||||||
return Err(Error::NoConfigDirectory);
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(system_path.join(sanitize_name(key)?))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the path of the key in the user's local config directory.
|
|
||||||
fn key_path(&self, key: &str) -> Result<PathBuf, Error> {
|
|
||||||
let Some(user_path) = self.user_path.as_ref() else {
|
|
||||||
return Err(Error::NoConfigDirectory);
|
|
||||||
};
|
|
||||||
Ok(user_path.join(sanitize_name(key)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getting any setting is available on a Config object
|
|
||||||
impl ConfigGet for Config {
|
|
||||||
//TODO: check for transaction
|
|
||||||
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
|
|
||||||
match self.get_local(key) {
|
|
||||||
Ok(value) => Ok(value),
|
|
||||||
Err(Error::NotFound) => self.get_system_default(key),
|
|
||||||
Err(why) => Err(why),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_local<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
|
|
||||||
// If key path exists
|
|
||||||
match self.key_path(key) {
|
|
||||||
Ok(key_path) if key_path.is_file() => {
|
|
||||||
// Load user override
|
|
||||||
let data = fs::read_to_string(key_path)
|
|
||||||
.map_err(|err| Error::GetKey(key.to_string(), err))?;
|
|
||||||
|
|
||||||
Ok(ron::from_str(&data)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => Err(Error::NotFound),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_system_default<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
|
|
||||||
// Load system default
|
|
||||||
let default_path = self.default_path(key)?;
|
|
||||||
let data =
|
|
||||||
fs::read_to_string(default_path).map_err(|err| Error::GetKey(key.to_string(), err))?;
|
|
||||||
Ok(ron::from_str(&data)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setting any setting in this way will do one transaction per set call
|
|
||||||
impl ConfigSet for Config {
|
|
||||||
fn set<T: Serialize>(&self, key: &str, value: T) -> Result<(), Error> {
|
|
||||||
// Wrap up single key/value sets in a transaction
|
|
||||||
let tx = self.transaction();
|
|
||||||
tx.set(key, value)?;
|
|
||||||
tx.commit()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use = "Config transaction must be committed"]
|
|
||||||
pub struct ConfigTransaction<'a> {
|
|
||||||
config: &'a Config,
|
|
||||||
//TODO: use map?
|
|
||||||
updates: Mutex<Vec<(PathBuf, String)>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConfigTransaction<'_> {
|
|
||||||
/// Apply all pending changes from ConfigTransaction
|
|
||||||
//TODO: apply all changes at once
|
|
||||||
pub fn commit(self) -> Result<(), Error> {
|
|
||||||
let mut updates = self.updates.lock().unwrap();
|
|
||||||
for (key_path, data) in updates.drain(..) {
|
|
||||||
atomicwrites::AtomicFile::new(
|
|
||||||
key_path,
|
|
||||||
atomicwrites::OverwriteBehavior::AllowOverwrite,
|
|
||||||
)
|
|
||||||
.write(|file| file.write_all(data.as_bytes()))?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setting any setting in this way will do one transaction for all settings
|
|
||||||
// when commit finishes that transaction
|
|
||||||
impl ConfigSet for ConfigTransaction<'_> {
|
|
||||||
fn set<T: Serialize>(&self, key: &str, value: T) -> Result<(), Error> {
|
|
||||||
//TODO: sanitize key (no slashes, cannot be . or ..)
|
|
||||||
let key_path = self.config.key_path(key)?;
|
|
||||||
let data = ron::ser::to_string_pretty(&value, ron::ser::PrettyConfig::new())?;
|
|
||||||
//TODO: replace duplicates?
|
|
||||||
{
|
|
||||||
let mut updates = self.updates.lock().unwrap();
|
|
||||||
updates.push((key_path, data));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait CosmicConfigEntry
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
const VERSION: u64;
|
|
||||||
|
|
||||||
fn write_entry(&self, config: &Config) -> Result<(), crate::Error>;
|
|
||||||
fn get_entry(config: &Config) -> Result<Self, (Vec<crate::Error>, Self)>;
|
|
||||||
/// Returns the keys that were updated
|
|
||||||
fn update_keys<T: AsRef<str>>(
|
|
||||||
&mut self,
|
|
||||||
config: &Config,
|
|
||||||
changed_keys: &[T],
|
|
||||||
) -> (Vec<crate::Error>, Vec<&'static str>);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Update<T> {
|
|
||||||
pub errors: Vec<crate::Error>,
|
|
||||||
pub keys: Vec<&'static str>,
|
|
||||||
pub config: T,
|
|
||||||
}
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
use iced_futures::futures::{SinkExt, Stream};
|
|
||||||
use iced_futures::{futures::channel::mpsc, stream};
|
|
||||||
use notify::RecommendedWatcher;
|
|
||||||
use std::{borrow::Cow, hash::Hash};
|
|
||||||
|
|
||||||
use crate::{Config, CosmicConfigEntry};
|
|
||||||
|
|
||||||
pub enum ConfigState<T> {
|
|
||||||
Init(Cow<'static, str>, u64, bool),
|
|
||||||
Waiting(T, RecommendedWatcher, mpsc::Receiver<Vec<String>>, Config),
|
|
||||||
Failed,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ConfigUpdate<T> {
|
|
||||||
Update(crate::Update<T>),
|
|
||||||
Failed,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cold]
|
|
||||||
pub fn config_subscription<
|
|
||||||
I: 'static + Hash,
|
|
||||||
T: 'static + Send + Sync + PartialEq + Clone + CosmicConfigEntry,
|
|
||||||
>(
|
|
||||||
id: I,
|
|
||||||
config_id: Cow<'static, str>,
|
|
||||||
config_version: u64,
|
|
||||||
) -> iced_futures::Subscription<crate::Update<T>> {
|
|
||||||
iced_futures::Subscription::run_with(
|
|
||||||
(id, config_id, config_version, false),
|
|
||||||
// FIXME there are type issues related to the 'static lifetime of the Cow if this is extracted to a named function...
|
|
||||||
|(_, config_id, config_version, is_state)| {
|
|
||||||
let config_id = config_id.clone();
|
|
||||||
let config_version = *config_version;
|
|
||||||
let is_state = *is_state;
|
|
||||||
|
|
||||||
stream::channel(100, move |mut output| async move {
|
|
||||||
let config_id = config_id.clone();
|
|
||||||
let mut state = ConfigState::Init(config_id, config_version, is_state);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
state = start_listening::<T>(state, &mut output).await;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cold]
|
|
||||||
pub fn config_state_subscription<
|
|
||||||
I: 'static + Hash,
|
|
||||||
T: 'static + Send + Sync + PartialEq + Clone + CosmicConfigEntry,
|
|
||||||
>(
|
|
||||||
id: I,
|
|
||||||
config_id: Cow<'static, str>,
|
|
||||||
config_version: u64,
|
|
||||||
) -> iced_futures::Subscription<crate::Update<T>> {
|
|
||||||
iced_futures::Subscription::run_with(
|
|
||||||
(id, config_id, config_version, true),
|
|
||||||
|(_, config_id, config_version, is_state)| {
|
|
||||||
let config_id = config_id.clone();
|
|
||||||
let config_version = *config_version;
|
|
||||||
let is_state = *is_state;
|
|
||||||
|
|
||||||
stream::channel(100, move |mut output| async move {
|
|
||||||
let config_id = config_id.clone();
|
|
||||||
let mut state = ConfigState::Init(config_id, config_version, is_state);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
state = start_listening::<T>(state, &mut output).await;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn start_listening<T: 'static + Send + Sync + PartialEq + Clone + CosmicConfigEntry>(
|
|
||||||
state: ConfigState<T>,
|
|
||||||
output: &mut mpsc::Sender<crate::Update<T>>,
|
|
||||||
) -> ConfigState<T> {
|
|
||||||
use iced_futures::futures::{StreamExt, future::pending};
|
|
||||||
|
|
||||||
match state {
|
|
||||||
ConfigState::Init(config_id, version, is_state) => {
|
|
||||||
let (tx, rx) = mpsc::channel(100);
|
|
||||||
let Ok(config) = (if is_state {
|
|
||||||
Config::new_state(&config_id, version)
|
|
||||||
} else {
|
|
||||||
Config::new(&config_id, version)
|
|
||||||
}) else {
|
|
||||||
return ConfigState::Failed;
|
|
||||||
};
|
|
||||||
let Ok(watcher) = config.watch(move |_helper, keys| {
|
|
||||||
let mut tx = tx.clone();
|
|
||||||
let _ = tx.try_send(keys.to_vec());
|
|
||||||
}) else {
|
|
||||||
return ConfigState::Failed;
|
|
||||||
};
|
|
||||||
|
|
||||||
match T::get_entry(&config) {
|
|
||||||
Ok(t) => {
|
|
||||||
let update = crate::Update {
|
|
||||||
errors: Vec::new(),
|
|
||||||
keys: Vec::new(),
|
|
||||||
config: t.clone(),
|
|
||||||
};
|
|
||||||
_ = output.send(update).await;
|
|
||||||
ConfigState::Waiting(t, watcher, rx, config)
|
|
||||||
}
|
|
||||||
Err((errors, t)) => {
|
|
||||||
let update = crate::Update {
|
|
||||||
errors,
|
|
||||||
keys: Vec::new(),
|
|
||||||
config: t.clone(),
|
|
||||||
};
|
|
||||||
_ = output.send(update).await;
|
|
||||||
ConfigState::Waiting(t, watcher, rx, config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ConfigState::Waiting(mut conf_data, watcher, mut rx, config) => match rx.next().await {
|
|
||||||
Some(keys) => {
|
|
||||||
let (errors, changed) = conf_data.update_keys(&config, &keys);
|
|
||||||
|
|
||||||
if !changed.is_empty() {
|
|
||||||
_ = output
|
|
||||||
.send(crate::Update {
|
|
||||||
errors,
|
|
||||||
keys: changed,
|
|
||||||
config: conf_data.clone(),
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
ConfigState::Waiting(conf_data, watcher, rx, config)
|
|
||||||
}
|
|
||||||
None => ConfigState::Failed,
|
|
||||||
},
|
|
||||||
ConfigState::Failed => pending().await,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 5252095787cc96e2aed64604158f94e450703455
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "cosmic-theme"
|
|
||||||
version = "1.0.0"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
features = ["test_all_features"]
|
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["export"]
|
|
||||||
export = ["serde_json"]
|
|
||||||
no-default = []
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
palette = { version = "0.7.6", features = ["serializing"] }
|
|
||||||
almost = "0.2"
|
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
|
||||||
serde_json = { version = "1.0.149", optional = true, features = [
|
|
||||||
"preserve_order",
|
|
||||||
] }
|
|
||||||
ron = "0.12.0"
|
|
||||||
csscolorparser = { version = "0.8.3", features = ["serde"] }
|
|
||||||
cosmic-config = { path = "../cosmic-config/", default-features = false, features = [
|
|
||||||
"subscription",
|
|
||||||
"macro",
|
|
||||||
] }
|
|
||||||
configparser = "3.1.0"
|
|
||||||
dirs.workspace = true
|
|
||||||
thiserror = "2.0.18"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
insta = "1.47.2"
|
|
||||||
|
|
||||||
[profile.dev.package]
|
|
||||||
insta.opt-level = 3
|
|
||||||
similar.opt-level = 3
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
# WIP
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
use palette::Srgba;
|
|
||||||
|
|
||||||
/// straight alpha "A over B" operator on non-linear srgba
|
|
||||||
pub fn over<A: Into<Srgba>, B: Into<Srgba>>(a: A, b: B) -> Srgba {
|
|
||||||
let a = a.into();
|
|
||||||
let b = b.into();
|
|
||||||
let o_a = (alpha_over(a.alpha, b.alpha)).clamp(0.0, 1.0);
|
|
||||||
let o_r = (c_over(a.red, b.red, a.alpha, b.alpha, o_a)).clamp(0.0, 1.0);
|
|
||||||
let o_g = (c_over(a.green, b.green, a.alpha, b.alpha, o_a)).clamp(0.0, 1.0);
|
|
||||||
let o_b = (c_over(a.blue, b.blue, a.alpha, b.alpha, o_a)).clamp(0.0, 1.0);
|
|
||||||
|
|
||||||
Srgba::new(o_r, o_g, o_b, o_a)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alpha_over(a: f32, b: f32) -> f32 {
|
|
||||||
a + b * (1.0 - a)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn c_over(a: f32, b: f32, a_alpha: f32, b_alpha: f32, o_alpha: f32) -> f32 {
|
|
||||||
a * a_alpha + b * b_alpha * (1.0 - a_alpha) / o_alpha
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
|
||||||
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
|
|
||||||
|
|
||||||
//! Cosmic theme library.
|
|
||||||
//!
|
|
||||||
//! Provides utilities for creating custom cosmic themes.
|
|
||||||
//!
|
|
||||||
|
|
||||||
pub use model::*;
|
|
||||||
|
|
||||||
mod model;
|
|
||||||
|
|
||||||
#[cfg(feature = "export")]
|
|
||||||
mod output;
|
|
||||||
|
|
||||||
/// composite colors in srgb
|
|
||||||
pub mod composite;
|
|
||||||
/// get color steps
|
|
||||||
pub mod steps;
|
|
||||||
|
|
||||||
/// name of cosmic theme
|
|
||||||
pub const NAME: &str = "com.system76.CosmicTheme";
|
|
||||||
|
|
||||||
pub use palette;
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
/// Corner radii variables for the Cosmic theme
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)]
|
|
||||||
pub struct CornerRadii {
|
|
||||||
/// corner radii of 0
|
|
||||||
pub radius_0: [f32; 4],
|
|
||||||
/// smallest size of corner radii that can be non-zero
|
|
||||||
pub radius_xs: [f32; 4],
|
|
||||||
/// small corner radii
|
|
||||||
pub radius_s: [f32; 4],
|
|
||||||
/// medium corner radii
|
|
||||||
pub radius_m: [f32; 4],
|
|
||||||
/// large corner radii
|
|
||||||
pub radius_l: [f32; 4],
|
|
||||||
/// extra large corner radii
|
|
||||||
pub radius_xl: [f32; 4],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CornerRadii {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
radius_0: [0.0; 4],
|
|
||||||
radius_xs: [4.0; 4],
|
|
||||||
radius_s: [8.0; 4],
|
|
||||||
radius_m: [16.0; 4],
|
|
||||||
radius_l: [32.0; 4],
|
|
||||||
radius_xl: [160.0; 4],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,181 +0,0 @@
|
||||||
use palette::Srgba;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::sync::LazyLock;
|
|
||||||
|
|
||||||
/// built-in light palette
|
|
||||||
pub static LIGHT_PALETTE: LazyLock<CosmicPalette> =
|
|
||||||
LazyLock::new(|| ron::from_str(include_str!("light.ron")).unwrap());
|
|
||||||
|
|
||||||
/// built-in dark palette
|
|
||||||
pub static DARK_PALETTE: LazyLock<CosmicPalette> =
|
|
||||||
LazyLock::new(|| ron::from_str(include_str!("dark.ron")).unwrap());
|
|
||||||
|
|
||||||
/// Palette type
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
|
||||||
pub enum CosmicPalette {
|
|
||||||
/// Dark mode
|
|
||||||
Dark(CosmicPaletteInner),
|
|
||||||
/// Light mode
|
|
||||||
Light(CosmicPaletteInner),
|
|
||||||
/// High contrast light mode
|
|
||||||
HighContrastLight(CosmicPaletteInner),
|
|
||||||
/// High contrast dark mode
|
|
||||||
HighContrastDark(CosmicPaletteInner),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CosmicPalette {
|
|
||||||
/// extract the inner palette
|
|
||||||
#[inline]
|
|
||||||
pub fn inner(self) -> CosmicPaletteInner {
|
|
||||||
match self {
|
|
||||||
CosmicPalette::Dark(p) => p,
|
|
||||||
CosmicPalette::Light(p) => p,
|
|
||||||
CosmicPalette::HighContrastLight(p) => p,
|
|
||||||
CosmicPalette::HighContrastDark(p) => p,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsMut<CosmicPaletteInner> for CosmicPalette {
|
|
||||||
#[inline]
|
|
||||||
fn as_mut(&mut self) -> &mut CosmicPaletteInner {
|
|
||||||
match self {
|
|
||||||
CosmicPalette::Dark(p) => p,
|
|
||||||
CosmicPalette::Light(p) => p,
|
|
||||||
CosmicPalette::HighContrastLight(p) => p,
|
|
||||||
CosmicPalette::HighContrastDark(p) => p,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<CosmicPaletteInner> for CosmicPalette {
|
|
||||||
#[inline]
|
|
||||||
fn as_ref(&self) -> &CosmicPaletteInner {
|
|
||||||
match self {
|
|
||||||
CosmicPalette::Dark(p) => p,
|
|
||||||
CosmicPalette::Light(p) => p,
|
|
||||||
CosmicPalette::HighContrastLight(p) => p,
|
|
||||||
CosmicPalette::HighContrastDark(p) => p,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CosmicPalette {
|
|
||||||
/// check if the palette is dark
|
|
||||||
#[inline]
|
|
||||||
pub fn is_dark(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
CosmicPalette::Dark(_) | CosmicPalette::HighContrastDark(_) => true,
|
|
||||||
CosmicPalette::Light(_) | CosmicPalette::HighContrastLight(_) => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// check if the palette is high_contrast
|
|
||||||
#[inline]
|
|
||||||
pub fn is_high_contrast(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
CosmicPalette::HighContrastLight(_) | CosmicPalette::HighContrastDark(_) => true,
|
|
||||||
CosmicPalette::Light(_) | CosmicPalette::Dark(_) => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CosmicPalette {
|
|
||||||
#[inline]
|
|
||||||
fn default() -> Self {
|
|
||||||
CosmicPalette::Dark(Default::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The palette for Cosmic Theme, from which all color properties are derived
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
|
|
||||||
pub struct CosmicPaletteInner {
|
|
||||||
/// name of the palette
|
|
||||||
pub name: String,
|
|
||||||
|
|
||||||
/// Utility Colors
|
|
||||||
/// Colors used for various points of emphasis in the UI.
|
|
||||||
pub bright_red: Srgba,
|
|
||||||
/// Colors used for various points of emphasis in the UI.
|
|
||||||
pub bright_green: Srgba,
|
|
||||||
/// Colors used for various points of emphasis in the UI.
|
|
||||||
pub bright_orange: Srgba,
|
|
||||||
|
|
||||||
/// Surface Grays
|
|
||||||
/// Colors used for three levels of surfaces in the UI.
|
|
||||||
pub gray_1: Srgba,
|
|
||||||
/// Colors used for three levels of surfaces in the UI.
|
|
||||||
pub gray_2: Srgba,
|
|
||||||
|
|
||||||
/// System Neutrals
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_0: Srgba,
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_1: Srgba,
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_2: Srgba,
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_3: Srgba,
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_4: Srgba,
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_5: Srgba,
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_6: Srgba,
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_7: Srgba,
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_8: Srgba,
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_9: Srgba,
|
|
||||||
/// A wider spread of dark colors for more general use.
|
|
||||||
pub neutral_10: Srgba,
|
|
||||||
|
|
||||||
/// Potential Accent Color Combos
|
|
||||||
pub accent_blue: Srgba,
|
|
||||||
/// Potential Accent Color Combos
|
|
||||||
pub accent_indigo: Srgba,
|
|
||||||
/// Potential Accent Color Combos
|
|
||||||
pub accent_purple: Srgba,
|
|
||||||
/// Potential Accent Color Combos
|
|
||||||
pub accent_pink: Srgba,
|
|
||||||
/// Potential Accent Color Combos
|
|
||||||
pub accent_red: Srgba,
|
|
||||||
/// Potential Accent Color Combos
|
|
||||||
pub accent_orange: Srgba,
|
|
||||||
/// Potential Accent Color Combos
|
|
||||||
pub accent_yellow: Srgba,
|
|
||||||
/// Potential Accent Color Combos
|
|
||||||
pub accent_green: Srgba,
|
|
||||||
/// Potential Accent Color Combos
|
|
||||||
pub accent_warm_grey: Srgba,
|
|
||||||
|
|
||||||
/// Extended Color Palette
|
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
|
||||||
pub ext_warm_grey: Srgba,
|
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
|
||||||
pub ext_orange: Srgba,
|
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
|
||||||
pub ext_yellow: Srgba,
|
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
|
||||||
pub ext_blue: Srgba,
|
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
|
||||||
pub ext_purple: Srgba,
|
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
|
||||||
pub ext_pink: Srgba,
|
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
|
||||||
pub ext_indigo: Srgba,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CosmicPalette {
|
|
||||||
/// name of the palette
|
|
||||||
#[inline]
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
match &self {
|
|
||||||
CosmicPalette::Dark(p) => &p.name,
|
|
||||||
CosmicPalette::Light(p) => &p.name,
|
|
||||||
CosmicPalette::HighContrastLight(p) => &p.name,
|
|
||||||
CosmicPalette::HighContrastDark(p) => &p.name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Dark((name:"cosmic-dark",bright_red:(red:1.0,green:0.62745098,blue:0.60392157,alpha:1.0),bright_green:(red:0.36862745,green:0.85882352,blue:0.54901960,alpha:1.0),bright_orange:(red:1.0,green:0.63921569,blue:0.49019608,alpha:1.0),gray_1:(red:0.10588235,green:0.10588235,blue:0.10588235,alpha:1.0),gray_2:(red:0.14901961,green:0.14901961,blue:0.14901961,alpha:1.0),neutral_0:(red:0.0,green:0.0,blue:0.0,alpha:1.0),neutral_1:(red:0.01176471,green:0.01176471,blue:0.01176471,alpha:1.0),neutral_2:(red:0.08627451,green:0.08627451,blue:0.08627451,alpha:1.0),neutral_3:(red:0.18039216,green:0.18039216,blue:0.18039216,alpha:1.0),neutral_4:(red:0.28235294,green:0.28235294,blue:0.28235294,alpha:1.0),neutral_5:(red:0.38823529,green:0.38823529,blue:0.38823529,alpha:1.0),neutral_6:(red:0.50196078,green:0.50196078,blue:0.50196078,alpha:1.0),neutral_7:(red:0.61960784,green:0.61960784,blue:0.61960784,alpha:1.0),neutral_8:(red:0.74509804,green:0.74509804,blue:0.74509804,alpha:1.0),neutral_9:(red:0.87058824,green:0.87058824,blue:0.87058824,alpha:1.0),neutral_10:(red:1.0,green:1.0,blue:1.0,alpha:1.0),accent_blue:(red:0.3882353,green:0.81568627,blue:0.87450981,alpha:1.0),accent_indigo:(red:0.63137255,green:0.75294118,blue:0.92156863,alpha:1.0),accent_purple:(red:0.90588235,green:0.61176471,blue:0.99607843,alpha:1.0),accent_pink:(red:1.0,green:0.61176471,blue:0.69411765,alpha:1.0),accent_red:(red:0.99215686,green:0.63137255,blue:0.62745098,alpha:1.0),accent_orange:(red:1.0,green:0.67843137,blue:0.0,alpha:1.0),accent_yellow:(red:0.96862745,green:0.87843137,blue:0.38431373,alpha:1.0),accent_green:(red:0.57254902,green:0.81176471,blue:0.61176471,alpha:1.0),accent_warm_grey:(red:0.79215686,green:0.72941176,blue:0.70588235,alpha:1.0),ext_warm_grey:(red:0.60784314,green:0.55686275,blue:0.54117647,alpha:1.0),ext_orange:(red:1.0,green:0.67843137,blue:0.0,alpha:1.0),ext_yellow:(red:0.99607843,green:0.85882353,blue:0.25098039,alpha:1.0),ext_blue:(red:0.28235294,green:0.72549020,blue:0.78039216,alpha:1.0),ext_purple:(red:0.81176471,green:0.49019608,blue:1.0,alpha:1.0),ext_pink:(red:0.97647059,green:0.22745098,blue:0.51372549,alpha:1.0),ext_indigo:(red:0.24313725,green:0.53333333,blue:1.0,alpha:1.0)))
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
use crate::Spacing;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
/// Density options for the Cosmic theme
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub enum Density {
|
|
||||||
/// Lower padding/spacing of elements
|
|
||||||
Compact,
|
|
||||||
/// Higher padding/spacing of elements
|
|
||||||
Spacious,
|
|
||||||
/// Standard padding/spacing of elements
|
|
||||||
#[default]
|
|
||||||
Standard,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Density> for Spacing {
|
|
||||||
fn from(value: Density) -> Self {
|
|
||||||
match value {
|
|
||||||
Density::Compact => Spacing {
|
|
||||||
space_none: 0,
|
|
||||||
space_xxxs: 4,
|
|
||||||
space_xxs: 4,
|
|
||||||
space_xs: 8,
|
|
||||||
space_s: 8,
|
|
||||||
space_m: 16,
|
|
||||||
space_l: 24,
|
|
||||||
space_xl: 32,
|
|
||||||
space_xxl: 48,
|
|
||||||
space_xxxl: 64,
|
|
||||||
},
|
|
||||||
Density::Spacious => Spacing {
|
|
||||||
space_none: 4,
|
|
||||||
space_xxxs: 8,
|
|
||||||
space_xxs: 12,
|
|
||||||
space_xs: 16,
|
|
||||||
space_s: 24,
|
|
||||||
space_m: 32,
|
|
||||||
space_l: 48,
|
|
||||||
space_xl: 64,
|
|
||||||
space_xxl: 128,
|
|
||||||
space_xxxl: 160,
|
|
||||||
},
|
|
||||||
Density::Standard => Spacing {
|
|
||||||
space_none: 0,
|
|
||||||
space_xxxs: 4,
|
|
||||||
space_xxs: 8,
|
|
||||||
space_xs: 12,
|
|
||||||
space_s: 16,
|
|
||||||
space_m: 24,
|
|
||||||
space_l: 32,
|
|
||||||
space_xl: 48,
|
|
||||||
space_xxl: 64,
|
|
||||||
space_xxxl: 128,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Spacing> for Density {
|
|
||||||
fn from(value: Spacing) -> Self {
|
|
||||||
if value.space_m.saturating_sub(16) == 0 {
|
|
||||||
Self::Compact
|
|
||||||
} else if value.space_m.saturating_sub(24) == 0 {
|
|
||||||
Self::Standard
|
|
||||||
} else {
|
|
||||||
Self::Spacious
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,203 +0,0 @@
|
||||||
use palette::{Srgba, WithAlpha};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::composite::over;
|
|
||||||
|
|
||||||
/// Theme Container colors of a theme, can be a theme background container, primary container, or secondary container
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
|
|
||||||
#[must_use]
|
|
||||||
pub struct Container {
|
|
||||||
/// the color of the container
|
|
||||||
pub base: Srgba,
|
|
||||||
/// the color of components in the container
|
|
||||||
pub component: Component,
|
|
||||||
/// the color of dividers in the container
|
|
||||||
pub divider: Srgba,
|
|
||||||
/// the color of text in the container
|
|
||||||
pub on: Srgba,
|
|
||||||
/// the color of @small_widget_container
|
|
||||||
pub small_widget: Srgba,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Container {
|
|
||||||
pub(crate) fn new(
|
|
||||||
component: Component,
|
|
||||||
base: Srgba,
|
|
||||||
on: Srgba,
|
|
||||||
mut small_widget: Srgba,
|
|
||||||
is_high_contrast: bool,
|
|
||||||
) -> Self {
|
|
||||||
let divider_c = on.with_alpha(if is_high_contrast { 0.5 } else { 0.2 });
|
|
||||||
small_widget.alpha = 0.25;
|
|
||||||
|
|
||||||
Self {
|
|
||||||
base,
|
|
||||||
component,
|
|
||||||
divider: over(divider_c, base),
|
|
||||||
on,
|
|
||||||
small_widget,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The colors for a widget of the Cosmic theme
|
|
||||||
#[derive(Clone, PartialEq, Debug, Default, Deserialize, Serialize)]
|
|
||||||
#[must_use]
|
|
||||||
pub struct Component {
|
|
||||||
/// The base color of the widget
|
|
||||||
pub base: Srgba,
|
|
||||||
/// The color of the widget when it is hovered
|
|
||||||
pub hover: Srgba,
|
|
||||||
/// the color of the widget when it is pressed
|
|
||||||
pub pressed: Srgba,
|
|
||||||
/// the color of the widget when it is selected
|
|
||||||
pub selected: Srgba,
|
|
||||||
/// the color of the widget when it is selected
|
|
||||||
pub selected_text: Srgba,
|
|
||||||
/// the color of the widget when it is focused
|
|
||||||
pub focus: Srgba,
|
|
||||||
/// the color of dividers for this widget
|
|
||||||
pub divider: Srgba,
|
|
||||||
/// the color of text for this widget
|
|
||||||
pub on: Srgba,
|
|
||||||
// the color of text with opacity 80 for this widget
|
|
||||||
// pub text_opacity_80: Srgba,
|
|
||||||
/// the color of the widget when it is disabled
|
|
||||||
pub disabled: Srgba,
|
|
||||||
/// the color of text in the widget when it is disabled
|
|
||||||
pub on_disabled: Srgba,
|
|
||||||
/// the color of the border for the widget
|
|
||||||
pub border: Srgba,
|
|
||||||
/// the color of the border for the widget when it is disabled
|
|
||||||
pub disabled_border: Srgba,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::must_use_candidate)]
|
|
||||||
#[allow(clippy::doc_markdown)]
|
|
||||||
impl Component {
|
|
||||||
#[inline]
|
|
||||||
/// get @hover_state_color
|
|
||||||
pub fn hover_state_color(&self) -> Srgba {
|
|
||||||
self.hover
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// get @pressed_state_color
|
|
||||||
pub fn pressed_state_color(&self) -> Srgba {
|
|
||||||
self.pressed
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// get @selected_state_color
|
|
||||||
pub fn selected_state_color(&self) -> Srgba {
|
|
||||||
self.selected
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// get @selected_state_text_color
|
|
||||||
pub fn selected_state_text_color(&self) -> Srgba {
|
|
||||||
self.selected_text
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// get @focus_color
|
|
||||||
pub fn focus_color(&self) -> Srgba {
|
|
||||||
self.focus
|
|
||||||
}
|
|
||||||
|
|
||||||
/// helper for producing a component from a base color a neutral and an accent
|
|
||||||
pub fn colored_component(
|
|
||||||
base: Srgba,
|
|
||||||
neutral: Srgba,
|
|
||||||
accent: Srgba,
|
|
||||||
hovered: Srgba,
|
|
||||||
pressed: Srgba,
|
|
||||||
) -> Self {
|
|
||||||
let mut base_50 = base;
|
|
||||||
base_50.alpha *= 0.5;
|
|
||||||
|
|
||||||
let on_20 = neutral;
|
|
||||||
let on_50 = on_20.with_alpha(0.5);
|
|
||||||
|
|
||||||
Component {
|
|
||||||
base,
|
|
||||||
hover: over(hovered, base),
|
|
||||||
pressed: over(pressed, base),
|
|
||||||
selected: over(hovered, base),
|
|
||||||
selected_text: accent,
|
|
||||||
divider: on_20,
|
|
||||||
on: neutral,
|
|
||||||
disabled: over(base_50, base),
|
|
||||||
on_disabled: over(on_50, base),
|
|
||||||
focus: accent,
|
|
||||||
border: base,
|
|
||||||
disabled_border: base_50,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// helper for producing a button component
|
|
||||||
pub fn colored_button(
|
|
||||||
base: Srgba,
|
|
||||||
overlay: Srgba,
|
|
||||||
on_button: Srgba,
|
|
||||||
accent: Srgba,
|
|
||||||
hovered: Srgba,
|
|
||||||
pressed: Srgba,
|
|
||||||
) -> Self {
|
|
||||||
let mut component = Component::colored_component(base, overlay, accent, hovered, pressed);
|
|
||||||
component.on = on_button;
|
|
||||||
|
|
||||||
let on_disabled = on_button.with_alpha(0.5);
|
|
||||||
component.on_disabled = on_disabled;
|
|
||||||
|
|
||||||
component
|
|
||||||
}
|
|
||||||
|
|
||||||
/// helper for producing a component color theme
|
|
||||||
#[allow(clippy::self_named_constructors)]
|
|
||||||
pub fn component(
|
|
||||||
base: Srgba,
|
|
||||||
accent: Srgba,
|
|
||||||
on_component: Srgba,
|
|
||||||
hovered: Srgba,
|
|
||||||
pressed: Srgba,
|
|
||||||
is_high_contrast: bool,
|
|
||||||
border: Srgba,
|
|
||||||
) -> Self {
|
|
||||||
let mut base_50 = base;
|
|
||||||
base_50.alpha *= 0.5;
|
|
||||||
|
|
||||||
let on_20 = on_component.with_alpha(0.2);
|
|
||||||
let on_65 = on_20.with_alpha(0.65);
|
|
||||||
|
|
||||||
let mut disabled_border = border;
|
|
||||||
disabled_border.alpha *= 0.5;
|
|
||||||
|
|
||||||
Component {
|
|
||||||
base,
|
|
||||||
hover: if base.alpha < 0.001 {
|
|
||||||
hovered
|
|
||||||
} else {
|
|
||||||
over(hovered, base)
|
|
||||||
},
|
|
||||||
pressed: if base.alpha < 0.001 {
|
|
||||||
pressed
|
|
||||||
} else {
|
|
||||||
over(pressed, base)
|
|
||||||
},
|
|
||||||
selected: if base.alpha < 0.001 {
|
|
||||||
hovered
|
|
||||||
} else {
|
|
||||||
over(hovered, base)
|
|
||||||
},
|
|
||||||
selected_text: accent,
|
|
||||||
focus: accent,
|
|
||||||
divider: if is_high_contrast { on_65 } else { on_20 },
|
|
||||||
on: on_component,
|
|
||||||
disabled: base_50,
|
|
||||||
on_disabled: on_65,
|
|
||||||
border,
|
|
||||||
disabled_border,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Layout {
|
|
||||||
corner_radii: [u32; 4],
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Light((name:"cosmic-light",bright_red:(red:0.53725490,green:0.01568627,blue:0.09411765,alpha:1.0),bright_green:(red:0.0,green:0.34117647,blue:0.17254901,alpha:1.0),bright_orange:(red:0.47450980,green:0.17254902,blue:0.0,alpha:1.0),gray_1:(red:0.84313725,green:0.84313725,blue:0.84313725,alpha:1.0),gray_2:(red:0.89411765,green:0.89411765,blue:0.89411765,alpha:1.0),neutral_0:(red:1.0,green:1.0,blue:1.0,alpha:1.0),neutral_1:(red:0.87058824,green:0.87058824,blue:0.87058824,alpha:1.0),neutral_2:(red:0.74509804,green:0.74509804,blue:0.74509804,alpha:1.0),neutral_3:(red:0.61960784,green:0.61960784,blue:0.61960784,alpha:1.0),neutral_4:(red:0.50196078,green:0.50196078,blue:0.50196078,alpha:1.0),neutral_5:(red:0.38823529,green:0.38823529,blue:0.38823529,alpha:1.0),neutral_6:(red:0.28235294,green:0.28235294,blue:0.28235294,alpha:1.0),neutral_7:(red:0.18039216,green:0.18039216,blue:0.18039216,alpha:1.0),neutral_8:(red:0.08627451,green:0.08627451,blue:0.08627451,alpha:1.0),neutral_9:(red:0.01176471,green:0.01176471,blue:0.01176471,alpha:1.0),neutral_10:(red:0.0,green:0.0,blue:0.0,alpha:1.0),accent_blue:(red:0.0,green:0.32156863,blue:0.35294118,alpha:1.0),accent_indigo:(red:0.18039216,green:0.28627451,blue:0.42745098,alpha:1.0),accent_purple:(red:0.40784314,green:0.12941176,blue:0.48627451,alpha:1.0),accent_pink:(red:0.52549020,green:0.01568627,blue:0.22745098,alpha:1.0),accent_red:(red:0.47058824,green:0.16078431,blue:0.18039216,alpha:1.0),accent_orange:(red:0.38431373,green:0.25098039,blue:0.0,alpha:1.0),accent_yellow:(red:0.32549020,green:0.28235294,blue:0.0,alpha:1.0),accent_green:(red:0.09411765,green:0.33333333,blue:0.16078431,alpha:1.0),accent_warm_grey:(red:0.33333333,green:0.27843137,blue:0.25882353,alpha:1.0),ext_warm_grey:(red:0.60784314,green:0.55686275,blue:0.54117647,alpha:1.0),ext_orange:(red:0.98431373,green:0.72156863,blue:0.42352941,alpha:1.0),ext_yellow:(red:0.96862745,green:0.87843137,blue:0.38431373,alpha:1.0),ext_blue:(red:0.41568627,green:0.79215686,blue:0.84705882,alpha:1.0),ext_purple:(red:0.83529412,green:0.54901961,blue:1.0,alpha:1.0),ext_pink:(red:1.0,green:0.61176471,blue:0.86666667,alpha:1.0),ext_indigo:(red:0.58431373,green:0.76862745,blue:0.98823529,alpha:1.0)))
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
pub use corner::*;
|
|
||||||
pub use cosmic_palette::*;
|
|
||||||
pub use density::*;
|
|
||||||
pub use derivation::*;
|
|
||||||
pub use mode::*;
|
|
||||||
pub use spacing::*;
|
|
||||||
pub use theme::*;
|
|
||||||
|
|
||||||
mod corner;
|
|
||||||
mod cosmic_palette;
|
|
||||||
mod density;
|
|
||||||
mod derivation;
|
|
||||||
mod mode;
|
|
||||||
mod spacing;
|
|
||||||
mod theme;
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
use cosmic_config::{Config, ConfigGet, CosmicConfigEntry};
|
|
||||||
|
|
||||||
/// ID for the ThemeMode config
|
|
||||||
pub const THEME_MODE_ID: &str = "com.system76.CosmicTheme.Mode";
|
|
||||||
|
|
||||||
/// The config for cosmic theme dark / light settings
|
|
||||||
#[derive(
|
|
||||||
Debug, Clone, Copy, PartialEq, Eq, cosmic_config::cosmic_config_derive::CosmicConfigEntry,
|
|
||||||
)]
|
|
||||||
#[version = 1]
|
|
||||||
pub struct ThemeMode {
|
|
||||||
/// The theme dark mode setting.
|
|
||||||
pub is_dark: bool,
|
|
||||||
/// The theme auto-switch dark and light mode setting.
|
|
||||||
pub auto_switch: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ThemeMode {
|
|
||||||
#[inline]
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
is_dark: true,
|
|
||||||
auto_switch: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ThemeMode {
|
|
||||||
#[inline]
|
|
||||||
/// Check if the theme is currently using dark mode
|
|
||||||
pub fn is_dark(config: &Config) -> Result<bool, cosmic_config::Error> {
|
|
||||||
config.get::<bool>("is_dark")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// The current version of the theme mode config.
|
|
||||||
pub const fn version() -> u64 {
|
|
||||||
Self::VERSION
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Get the config for the theme mode
|
|
||||||
pub fn config() -> Result<Config, cosmic_config::Error> {
|
|
||||||
Config::new(THEME_MODE_ID, Self::VERSION)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
/// Spacing variables for the Cosmic theme
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
|
||||||
pub struct Spacing {
|
|
||||||
/// No spacing
|
|
||||||
pub space_none: u16,
|
|
||||||
/// smallest spacing that can be non-zero
|
|
||||||
pub space_xxxs: u16,
|
|
||||||
/// extra extra small spacing
|
|
||||||
pub space_xxs: u16,
|
|
||||||
/// extra small spacing
|
|
||||||
pub space_xs: u16,
|
|
||||||
/// small spacing
|
|
||||||
pub space_s: u16,
|
|
||||||
/// medium spacing
|
|
||||||
pub space_m: u16,
|
|
||||||
/// large spacing
|
|
||||||
pub space_l: u16,
|
|
||||||
/// extra large spacing
|
|
||||||
pub space_xl: u16,
|
|
||||||
/// extra extra large spacing
|
|
||||||
pub space_xxl: u16,
|
|
||||||
/// largest possible spacing
|
|
||||||
pub space_xxxl: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Spacing {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
space_none: 0,
|
|
||||||
space_xxxs: 4,
|
|
||||||
space_xxs: 8,
|
|
||||||
space_xs: 12,
|
|
||||||
space_s: 16,
|
|
||||||
space_m: 24,
|
|
||||||
space_l: 32,
|
|
||||||
space_xl: 48,
|
|
||||||
space_xxl: 64,
|
|
||||||
space_xxxl: 128,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,312 +0,0 @@
|
||||||
use crate::{Component, Theme, composite::over, steps::steps};
|
|
||||||
use palette::{Darken, IntoColor, Lighten, Srgba, WithAlpha, rgb::Rgba};
|
|
||||||
use std::{
|
|
||||||
fs::{self, File},
|
|
||||||
io::{self, Write},
|
|
||||||
num::NonZeroUsize,
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{OutputError, to_rgba};
|
|
||||||
|
|
||||||
impl Theme {
|
|
||||||
#[must_use]
|
|
||||||
#[cold]
|
|
||||||
/// turn the theme into css
|
|
||||||
pub fn as_gtk4(&self) -> String {
|
|
||||||
let Self {
|
|
||||||
background,
|
|
||||||
primary,
|
|
||||||
secondary,
|
|
||||||
accent,
|
|
||||||
destructive,
|
|
||||||
warning,
|
|
||||||
success,
|
|
||||||
palette,
|
|
||||||
..
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
let window_bg = to_rgba(background.base);
|
|
||||||
let window_fg = to_rgba(background.on);
|
|
||||||
|
|
||||||
let view_bg = to_rgba(primary.base);
|
|
||||||
let view_fg = to_rgba(primary.on);
|
|
||||||
|
|
||||||
let headerbar_bg = to_rgba(background.base);
|
|
||||||
let headerbar_fg = to_rgba(background.on);
|
|
||||||
let headerbar_border_color = to_rgba(background.divider);
|
|
||||||
|
|
||||||
let sidebar_bg = to_rgba(primary.base);
|
|
||||||
let sidebar_fg = to_rgba(primary.on);
|
|
||||||
let sidebar_shade = to_rgba(if self.is_dark {
|
|
||||||
Rgba::new(0.0, 0.0, 0.0, 0.08)
|
|
||||||
} else {
|
|
||||||
Rgba::new(0.0, 0.0, 0.0, 0.32)
|
|
||||||
});
|
|
||||||
let backdrop_overlay = Srgba::new(1.0, 1.0, 1.0, if self.is_dark { 0.08 } else { 0.32 });
|
|
||||||
let sidebar_backdrop = to_rgba(over(backdrop_overlay, primary.base));
|
|
||||||
|
|
||||||
let secondary_sidebar_bg = to_rgba(secondary.base);
|
|
||||||
let secondary_sidebar_fg = to_rgba(secondary.on);
|
|
||||||
let secondary_sidebar_shade = to_rgba(if self.is_dark {
|
|
||||||
Rgba::new(0.0, 0.0, 0.0, 0.08)
|
|
||||||
} else {
|
|
||||||
Rgba::new(0.0, 0.0, 0.0, 0.32)
|
|
||||||
});
|
|
||||||
let secondary_sidebar_backdrop = to_rgba(over(backdrop_overlay, secondary.base));
|
|
||||||
|
|
||||||
let headerbar_backdrop = to_rgba(background.base);
|
|
||||||
|
|
||||||
let card_bg = to_rgba(background.component.base);
|
|
||||||
let card_fg = to_rgba(background.component.on);
|
|
||||||
|
|
||||||
let thumbnail_bg = to_rgba(background.component.base);
|
|
||||||
let thumbnail_fg = to_rgba(background.component.on);
|
|
||||||
|
|
||||||
let dialog_bg = to_rgba(primary.base);
|
|
||||||
let dialog_fg = to_rgba(primary.on);
|
|
||||||
|
|
||||||
let popover_bg = to_rgba(background.component.base);
|
|
||||||
let popover_fg = to_rgba(background.component.on);
|
|
||||||
|
|
||||||
let shade = to_rgba(if self.is_dark {
|
|
||||||
Rgba::new(0.0, 0.0, 0.0, 0.32)
|
|
||||||
} else {
|
|
||||||
Rgba::new(0.0, 0.0, 0.0, 0.08)
|
|
||||||
});
|
|
||||||
|
|
||||||
let inverted_bg_divider = background.base.with_alpha(0.5);
|
|
||||||
let scrollbar_outline = to_rgba(inverted_bg_divider);
|
|
||||||
|
|
||||||
let mut css = format! {r#"/* GENERATED BY COSMIC */
|
|
||||||
@define-color window_bg_color {window_bg};
|
|
||||||
@define-color window_fg_color {window_fg};
|
|
||||||
|
|
||||||
@define-color view_bg_color {view_bg};
|
|
||||||
@define-color view_fg_color {view_fg};
|
|
||||||
|
|
||||||
@define-color headerbar_bg_color {headerbar_bg};
|
|
||||||
@define-color headerbar_fg_color {headerbar_fg};
|
|
||||||
@define-color headerbar_border_color_color {headerbar_border_color};
|
|
||||||
@define-color headerbar_backdrop_color {headerbar_backdrop};
|
|
||||||
|
|
||||||
@define-color sidebar_bg_color {sidebar_bg};
|
|
||||||
@define-color sidebar_fg_color {sidebar_fg};
|
|
||||||
@define-color sidebar_shade_color {sidebar_shade};
|
|
||||||
@define-color sidebar_backdrop_color {sidebar_backdrop};
|
|
||||||
|
|
||||||
@define-color secondary_sidebar_bg_color {secondary_sidebar_bg};
|
|
||||||
@define-color secondary_sidebar_fg_color {secondary_sidebar_fg};
|
|
||||||
@define-color secondary_sidebar_shade_color {secondary_sidebar_shade};
|
|
||||||
@define-color secondary_sidebar_backdrop_color {secondary_sidebar_backdrop};
|
|
||||||
|
|
||||||
@define-color card_bg_color {card_bg};
|
|
||||||
@define-color card_fg_color {card_fg};
|
|
||||||
|
|
||||||
@define-color thumbnail_bg_color {thumbnail_bg};
|
|
||||||
@define-color thumbnail_fg_color {thumbnail_fg};
|
|
||||||
|
|
||||||
@define-color dialog_bg_color {dialog_bg};
|
|
||||||
@define-color dialog_fg_color {dialog_fg};
|
|
||||||
|
|
||||||
@define-color popover_bg_color {popover_bg};
|
|
||||||
@define-color popover_fg_color {popover_fg};
|
|
||||||
|
|
||||||
@define-color shade_color {shade};
|
|
||||||
@define-color scrollbar_outline_color {scrollbar_outline};
|
|
||||||
"#};
|
|
||||||
|
|
||||||
css.push_str(&component_gtk4_css("accent", accent));
|
|
||||||
css.push_str(&component_gtk4_css("destructive", destructive));
|
|
||||||
css.push_str(&component_gtk4_css("warning", warning));
|
|
||||||
css.push_str(&component_gtk4_css("success", success));
|
|
||||||
css.push_str(&component_gtk4_css("accent", accent));
|
|
||||||
css.push_str(&component_gtk4_css("error", destructive));
|
|
||||||
|
|
||||||
css.push_str(&color_css("blue", palette.accent_blue));
|
|
||||||
css.push_str(&color_css("green", palette.accent_green));
|
|
||||||
css.push_str(&color_css("yellow", palette.accent_yellow));
|
|
||||||
css.push_str(&color_css("red", palette.accent_red));
|
|
||||||
css.push_str(&color_css("orange", palette.ext_orange));
|
|
||||||
css.push_str(&color_css("purple", palette.ext_purple));
|
|
||||||
let neutral_steps = steps(palette.neutral_5, NonZeroUsize::new(10).unwrap());
|
|
||||||
for (i, c) in neutral_steps[..5].iter().enumerate() {
|
|
||||||
css.push_str(&format!("@define-color light_{i} {};\n", to_rgba(*c)));
|
|
||||||
}
|
|
||||||
for (i, c) in neutral_steps[5..].iter().enumerate() {
|
|
||||||
css.push_str(&format!("@define-color dark_{i} {};\n", to_rgba(*c)));
|
|
||||||
}
|
|
||||||
css
|
|
||||||
}
|
|
||||||
|
|
||||||
/// write the CSS to the appropriate directory
|
|
||||||
/// Should be written in the XDG config directory for gtk-4.0
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns an `OutputError` if there is an error writing the CSS file.
|
|
||||||
#[cold]
|
|
||||||
pub fn write_gtk4(&self) -> Result<(), OutputError> {
|
|
||||||
let css_str = self.as_gtk4();
|
|
||||||
let Some(mut config_dir) = dirs::config_dir() else {
|
|
||||||
return Err(OutputError::MissingConfigDir);
|
|
||||||
};
|
|
||||||
|
|
||||||
let name = if self.is_dark {
|
|
||||||
"dark.css"
|
|
||||||
} else {
|
|
||||||
"light.css"
|
|
||||||
};
|
|
||||||
|
|
||||||
config_dir.extend(["gtk-4.0", "cosmic"]);
|
|
||||||
if !config_dir.exists() {
|
|
||||||
std::fs::create_dir_all(&config_dir).map_err(OutputError::Io)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let file_path = config_dir.join(name);
|
|
||||||
let tmp_file_path = config_dir.join(name.to_owned() + "~");
|
|
||||||
|
|
||||||
// Write to tmp_file_path first, then move it to file_path
|
|
||||||
let mut tmp_file = File::create(&tmp_file_path).map_err(OutputError::Io)?;
|
|
||||||
let res = tmp_file
|
|
||||||
.write_all(css_str.as_bytes())
|
|
||||||
.and_then(|_| tmp_file.flush())
|
|
||||||
.and_then(|_| std::fs::rename(&tmp_file_path, file_path));
|
|
||||||
if let Err(e) = res {
|
|
||||||
_ = std::fs::remove_file(&tmp_file_path);
|
|
||||||
return Err(OutputError::Io(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Apply gtk color variable settings
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns an `OutputError` if there is an error applying the CSS file.
|
|
||||||
#[cold]
|
|
||||||
pub fn apply_gtk(is_dark: bool) -> Result<(), OutputError> {
|
|
||||||
let Some(config_dir) = dirs::config_dir() else {
|
|
||||||
return Err(OutputError::MissingConfigDir);
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut gtk4 = config_dir.join("gtk-4.0");
|
|
||||||
let mut gtk3 = config_dir.join("gtk-3.0");
|
|
||||||
|
|
||||||
fs::create_dir_all(>k4).map_err(OutputError::Io)?;
|
|
||||||
fs::create_dir_all(>k3).map_err(OutputError::Io)?;
|
|
||||||
|
|
||||||
let cosmic_css_dir = gtk4.join("cosmic");
|
|
||||||
let cosmic_css = cosmic_css_dir.join(if is_dark { "dark.css" } else { "light.css" });
|
|
||||||
|
|
||||||
gtk4.push("gtk.css");
|
|
||||||
gtk3.push("gtk.css");
|
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
for gtk_dest in [>k4, >k3] {
|
|
||||||
use std::os::unix::fs::symlink;
|
|
||||||
Self::backup_non_cosmic_css(gtk_dest, &cosmic_css_dir).map_err(OutputError::Io)?;
|
|
||||||
|
|
||||||
if gtk_dest.exists() {
|
|
||||||
fs::remove_file(gtk_dest).map_err(OutputError::Io)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
symlink(&cosmic_css, gtk_dest).map_err(OutputError::Io)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reset the applied gtk css
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns an `OutputError` if there is an error resetting the CSS file.
|
|
||||||
#[cold]
|
|
||||||
pub fn reset_gtk() -> Result<(), OutputError> {
|
|
||||||
let Some(config_dir) = dirs::config_dir() else {
|
|
||||||
return Err(OutputError::MissingConfigDir);
|
|
||||||
};
|
|
||||||
|
|
||||||
let gtk4 = config_dir.join("gtk-4.0");
|
|
||||||
let gtk3 = config_dir.join("gtk-3.0");
|
|
||||||
let gtk4_dest = gtk4.join("gtk.css");
|
|
||||||
let cosmic_css = gtk4.join("cosmic");
|
|
||||||
let gtk3_dest = gtk3.join("gtk.css");
|
|
||||||
|
|
||||||
let res = Self::reset_cosmic_css(>k3_dest, &cosmic_css).map_err(OutputError::Io);
|
|
||||||
Self::reset_cosmic_css(>k4_dest, &cosmic_css).map_err(OutputError::Io)?;
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cold]
|
|
||||||
fn backup_non_cosmic_css(path: &Path, cosmic_css: &Path) -> io::Result<()> {
|
|
||||||
if !Self::is_cosmic_css(path, cosmic_css)?.unwrap_or(true) {
|
|
||||||
let backup_path = path.with_extension("css.bak");
|
|
||||||
fs::rename(path, &backup_path)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cold]
|
|
||||||
fn reset_cosmic_css(path: &Path, cosmic_css: &Path) -> io::Result<()> {
|
|
||||||
if Self::is_cosmic_css(path, cosmic_css)?.unwrap_or_default() {
|
|
||||||
fs::remove_file(path)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_cosmic_css(path: &Path, cosmic_css: &Path) -> io::Result<Option<bool>> {
|
|
||||||
if !path.exists() {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Ok(metadata) = fs::symlink_metadata(path) {
|
|
||||||
if metadata.file_type().is_symlink() {
|
|
||||||
if let Ok(actual_cosmic_css) = fs::read_link(path) {
|
|
||||||
let canonical_target = fs::canonicalize(&actual_cosmic_css)?;
|
|
||||||
let canonical_base = fs::canonicalize(cosmic_css)?;
|
|
||||||
return Ok(Some(
|
|
||||||
canonical_target == canonical_base
|
|
||||||
|| canonical_target.starts_with(&canonical_base),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Some(false))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn component_gtk4_css(prefix: &str, c: &Component) -> String {
|
|
||||||
format!(
|
|
||||||
r#"
|
|
||||||
@define-color {prefix}_color {};
|
|
||||||
@define-color {prefix}_bg_color {};
|
|
||||||
@define-color {prefix}_fg_color {};
|
|
||||||
"#,
|
|
||||||
to_rgba(c.base),
|
|
||||||
to_rgba(c.base),
|
|
||||||
to_rgba(c.on),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn color_css(prefix: &str, c_3: Srgba) -> String {
|
|
||||||
let oklch: palette::Oklch = c_3.into_color();
|
|
||||||
let c_2: Srgba = oklch.lighten(0.1).into_color();
|
|
||||||
let c_1: Srgba = oklch.lighten(0.2).into_color();
|
|
||||||
let c_4: Srgba = oklch.darken(0.1).into_color();
|
|
||||||
let c_5: Srgba = oklch.darken(0.2).into_color();
|
|
||||||
let c_1 = to_rgba(c_1);
|
|
||||||
let c_2 = to_rgba(c_2);
|
|
||||||
let c_3 = to_rgba(c_3);
|
|
||||||
let c_4 = to_rgba(c_4);
|
|
||||||
let c_5 = to_rgba(c_5);
|
|
||||||
|
|
||||||
format! {r#"
|
|
||||||
@define-color {prefix}_1 {c_1};
|
|
||||||
@define-color {prefix}_2 {c_2};
|
|
||||||
@define-color {prefix}_3 {c_3};
|
|
||||||
@define-color {prefix}_4 {c_4};
|
|
||||||
@define-color {prefix}_5 {c_5};
|
|
||||||
"#}
|
|
||||||
}
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
use configparser::ini::WriteOptions;
|
|
||||||
use palette::{Srgba, rgb::Rgba};
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use crate::Theme;
|
|
||||||
|
|
||||||
/// Module for outputting the Cosmic gtk4 theme type as CSS
|
|
||||||
pub mod gtk4_output;
|
|
||||||
|
|
||||||
/// Module for configuring qt5ct and qt6ct to use our qt theme
|
|
||||||
pub mod qt56ct_output;
|
|
||||||
/// Module for outputting the Cosmic qt theme type as kdeglobals
|
|
||||||
pub mod qt_output;
|
|
||||||
|
|
||||||
pub mod vs_code;
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum OutputError {
|
|
||||||
#[error("IO Error: {0}")]
|
|
||||||
Io(std::io::Error),
|
|
||||||
#[error("Missing config directory")]
|
|
||||||
MissingConfigDir,
|
|
||||||
#[error("Missing data directory")]
|
|
||||||
MissingDataDir,
|
|
||||||
#[error("Serde Error: {0}")]
|
|
||||||
Serde(#[from] serde_json::Error),
|
|
||||||
#[error("Ini Error: {0}")]
|
|
||||||
Ini(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Theme {
|
|
||||||
#[inline]
|
|
||||||
/// Apply COSMIC theme exports for GTK and Qt applications.
|
|
||||||
pub fn apply_exports(&self) -> Result<(), OutputError> {
|
|
||||||
let gtk_res = Theme::apply_gtk(self.is_dark);
|
|
||||||
let qt_res = Theme::apply_qt(self.is_dark);
|
|
||||||
let qt56ct_res = Theme::apply_qt56ct(self.is_dark);
|
|
||||||
gtk_res?;
|
|
||||||
qt_res?;
|
|
||||||
qt56ct_res?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Write COSMIC theme exports for GTK and Qt applications.
|
|
||||||
pub fn write_exports(&self) -> Result<(), OutputError> {
|
|
||||||
let gtk_res = self.write_gtk4();
|
|
||||||
let qt_res = self.write_qt();
|
|
||||||
let qt56ct_res = self.write_qt56ct();
|
|
||||||
gtk_res?;
|
|
||||||
qt_res?;
|
|
||||||
qt56ct_res?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Un-export GTK and Qt theme configurations applied by us.
|
|
||||||
pub fn reset_exports() -> Result<(), OutputError> {
|
|
||||||
let gtk_res = Theme::reset_gtk();
|
|
||||||
let qt_res = Theme::reset_qt();
|
|
||||||
let qt56ct_res = Theme::reset_qt56ct();
|
|
||||||
gtk_res?;
|
|
||||||
qt_res?;
|
|
||||||
qt56ct_res?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_hex(c: Srgba) -> String {
|
|
||||||
let c_u8: Rgba<palette::encoding::Srgb, u8> = c.into_format();
|
|
||||||
format!(
|
|
||||||
"{:02x}{:02x}{:02x}{:02x}",
|
|
||||||
c_u8.red, c_u8.green, c_u8.blue, c_u8.alpha
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_rgba(c: Srgba) -> String {
|
|
||||||
let c_u8: Rgba<palette::encoding::Srgb, u8> = c.into_format();
|
|
||||||
format!(
|
|
||||||
"rgba({}, {}, {}, {:1.2})",
|
|
||||||
c_u8.red, c_u8.green, c_u8.blue, c.alpha
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn qt_settings_ini_style() -> WriteOptions {
|
|
||||||
let mut write_options = WriteOptions::default();
|
|
||||||
write_options.blank_lines_between_sections = 1;
|
|
||||||
write_options
|
|
||||||
}
|
|
||||||
|
|
@ -1,415 +0,0 @@
|
||||||
use crate::Theme;
|
|
||||||
use configparser::ini::Ini;
|
|
||||||
use palette::{Mix, Srgba, WithAlpha, blend::Compose, rgb::Rgba};
|
|
||||||
use std::{
|
|
||||||
fs::{self, File},
|
|
||||||
io::Write,
|
|
||||||
path::PathBuf,
|
|
||||||
vec,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{OutputError, qt_settings_ini_style};
|
|
||||||
|
|
||||||
impl Theme {
|
|
||||||
/// The "version" of this theme.
|
|
||||||
///
|
|
||||||
/// To avoid repeatedly overwriting the user's config, we use a version system.
|
|
||||||
///
|
|
||||||
/// Increment this value when changes to qt{5,6}ct.conf are needed.
|
|
||||||
/// If the config's version is outdated, we update several sections.
|
|
||||||
/// Otherwise, only the light/dark mode is updated.
|
|
||||||
const COSMIC_QT_VERSION: u64 = 2;
|
|
||||||
|
|
||||||
/// Produces a QPalette ini file for qt5ct and qt6ct.
|
|
||||||
///
|
|
||||||
/// Example file: https://github.com/trialuser02/qt6ct/blob/master/colors/airy.conf
|
|
||||||
#[must_use]
|
|
||||||
#[cold]
|
|
||||||
pub fn as_qpalette(&self) -> String {
|
|
||||||
let lightest = if self.is_dark {
|
|
||||||
self.background.on
|
|
||||||
} else {
|
|
||||||
self.background.base
|
|
||||||
};
|
|
||||||
let darkest = if self.is_dark {
|
|
||||||
self.background.base
|
|
||||||
} else {
|
|
||||||
self.background.on
|
|
||||||
};
|
|
||||||
let active = QPaletteGroup {
|
|
||||||
window_text: self.background.on,
|
|
||||||
button: self.button.base,
|
|
||||||
light: self.button.base.mix(lightest, 0.1),
|
|
||||||
midlight: self.button.base.mix(lightest, 0.05),
|
|
||||||
dark: self.button.base.mix(darkest, 0.1),
|
|
||||||
mid: self.button.base.mix(darkest, 0.05),
|
|
||||||
text: self.background.component.on,
|
|
||||||
bright_text: lightest,
|
|
||||||
button_text: self.button.on,
|
|
||||||
base: self.background.component.base,
|
|
||||||
window: self.background.base,
|
|
||||||
shadow: darkest,
|
|
||||||
// selection colors are swapped to fix menu bar contrast
|
|
||||||
highlight: self.background.component.selected_text,
|
|
||||||
highlighted_text: self.background.component.selected,
|
|
||||||
link: self.link_button.on,
|
|
||||||
link_visited: self.link_button.on.mix(self.secondary.component.base, 0.2),
|
|
||||||
alternate_base: self.background.base.mix(self.accent.base, 0.05),
|
|
||||||
no_role: self.background.component.disabled,
|
|
||||||
tool_tip_base: self.background.component.base,
|
|
||||||
tool_tip_text: self.background.component.on,
|
|
||||||
placeholder_text: self.background.component.on.with_alpha(0.5),
|
|
||||||
};
|
|
||||||
let inactive = QPaletteGroup {
|
|
||||||
window_text: active.window_text.with_alpha(0.8),
|
|
||||||
text: active.text.with_alpha(0.8),
|
|
||||||
highlighted_text: active.highlighted_text.with_alpha(0.8),
|
|
||||||
tool_tip_text: active.tool_tip_text.with_alpha(0.8),
|
|
||||||
..active
|
|
||||||
};
|
|
||||||
let disabled = QPaletteGroup {
|
|
||||||
button: self.button.disabled,
|
|
||||||
text: self.background.component.on_disabled,
|
|
||||||
button_text: self.button.on_disabled,
|
|
||||||
base: self.background.component.disabled,
|
|
||||||
highlighted_text: active.highlighted_text.with_alpha(0.5),
|
|
||||||
link: self.link_button.on_disabled,
|
|
||||||
link_visited: self
|
|
||||||
.link_button
|
|
||||||
.on_disabled
|
|
||||||
.mix(self.secondary.component.disabled, 0.2),
|
|
||||||
alternate_base: self.background.base.mix(self.accent.disabled, 0.05),
|
|
||||||
tool_tip_base: self.background.component.disabled,
|
|
||||||
tool_tip_text: self.background.component.on_disabled,
|
|
||||||
placeholder_text: self.background.component.on_disabled.with_alpha(0.5),
|
|
||||||
..inactive
|
|
||||||
};
|
|
||||||
|
|
||||||
format!(
|
|
||||||
r#"# GENERATED BY COSMIC
|
|
||||||
|
|
||||||
[ColorScheme]
|
|
||||||
active_colors={}
|
|
||||||
disabled_colors={}
|
|
||||||
inactive_colors={}
|
|
||||||
"#,
|
|
||||||
active.as_list(),
|
|
||||||
disabled.as_list(),
|
|
||||||
inactive.as_list(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes the QPalette ini files to:
|
|
||||||
/// - `~/.config/qt6ct/colors/`
|
|
||||||
/// - `~/.config/qt5ct/colors/`
|
|
||||||
#[cold]
|
|
||||||
pub fn write_qt56ct(&self) -> Result<(), OutputError> {
|
|
||||||
let qpalette = self.as_qpalette();
|
|
||||||
let qt5ct_res = self.write_ct("qt5ct", &qpalette);
|
|
||||||
let qt6ct_res = self.write_ct("qt6ct", &qpalette);
|
|
||||||
qt5ct_res?;
|
|
||||||
qt6ct_res?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
#[must_use]
|
|
||||||
#[cold]
|
|
||||||
fn write_ct(&self, ct: &str, qpalette: &str) -> Result<(), OutputError> {
|
|
||||||
let file_path = Self::get_qpalette_path(ct, self.is_dark)?;
|
|
||||||
let tmp_file_path = file_path.with_extension("conf.new");
|
|
||||||
|
|
||||||
let mut tmp_file = File::create(&tmp_file_path).map_err(OutputError::Io)?;
|
|
||||||
let res = tmp_file
|
|
||||||
.write_all(qpalette.as_bytes())
|
|
||||||
.and_then(|_| tmp_file.flush())
|
|
||||||
.and_then(|_| std::fs::rename(&tmp_file_path, file_path));
|
|
||||||
if let Err(e) = res {
|
|
||||||
_ = std::fs::remove_file(&tmp_file_path);
|
|
||||||
return Err(OutputError::Io(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Edits qt{5,6}ct.conf to use COSMIC styles if needed.
|
|
||||||
#[cold]
|
|
||||||
pub fn apply_qt56ct(is_dark: bool) -> Result<(), OutputError> {
|
|
||||||
let qt5ct_res = Self::apply_ct("qt5ct", is_dark);
|
|
||||||
let qt6ct_res = Self::apply_ct("qt6ct", is_dark);
|
|
||||||
qt5ct_res?;
|
|
||||||
qt6ct_res?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
#[must_use]
|
|
||||||
#[cold]
|
|
||||||
fn apply_ct(ct: &str, is_dark: bool) -> Result<(), OutputError> {
|
|
||||||
let path = Self::get_conf_path(ct)?;
|
|
||||||
let file_content = fs::read_to_string(&path).map_err(OutputError::Io)?;
|
|
||||||
let mut ini = Ini::new_cs();
|
|
||||||
ini.read(file_content).map_err(OutputError::Ini)?;
|
|
||||||
|
|
||||||
let old_version = ini
|
|
||||||
.getuint("Appearance", "cosmic_qt_version")
|
|
||||||
.map_err(OutputError::Ini)?
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let color_scheme_path = Self::get_qpalette_path(ct, is_dark)?;
|
|
||||||
let icon_theme = if is_dark { "breeze-dark" } else { "breeze" };
|
|
||||||
|
|
||||||
ini.set(
|
|
||||||
"Appearance",
|
|
||||||
"cosmic_qt_version",
|
|
||||||
Some(Theme::COSMIC_QT_VERSION.to_string()),
|
|
||||||
);
|
|
||||||
|
|
||||||
if old_version < Theme::COSMIC_QT_VERSION {
|
|
||||||
// Config is outdated, update it unconditionally!
|
|
||||||
|
|
||||||
ini.setstr(
|
|
||||||
"Appearance",
|
|
||||||
"color_scheme_path",
|
|
||||||
color_scheme_path.to_str(),
|
|
||||||
);
|
|
||||||
// Enable the above color scheme, instead of using the default color scheme of e.g. Breeze
|
|
||||||
ini.setstr("Appearance", "custom_palette", Some("true"));
|
|
||||||
// COSMIC icons are stuck in light mode, so use breeze icons instead
|
|
||||||
ini.setstr("Appearance", "icon_theme", Some(icon_theme));
|
|
||||||
// Use COSMIC dialogs instead of KDE's
|
|
||||||
ini.setstr("Appearance", "standard_dialogs", Some("xdgdesktopportal"));
|
|
||||||
|
|
||||||
// TODO: Add fonts section to match COSMIC
|
|
||||||
} else {
|
|
||||||
// Config is not outdated, check before updating light/dark mode only!
|
|
||||||
|
|
||||||
let old_color_scheme_path = ini
|
|
||||||
.get("Appearance", "color_scheme_path")
|
|
||||||
.unwrap_or_else(|| "CosmicPlease".to_owned());
|
|
||||||
if old_color_scheme_path.contains("Cosmic") {
|
|
||||||
ini.setstr(
|
|
||||||
"Appearance",
|
|
||||||
"color_scheme_path",
|
|
||||||
color_scheme_path.to_str(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let old_icon_theme = ini
|
|
||||||
.get("Appearance", "icon_theme")
|
|
||||||
.unwrap_or_else(|| "breeze".to_owned());
|
|
||||||
if old_icon_theme.contains("breeze") {
|
|
||||||
ini.setstr("Appearance", "icon_theme", Some(icon_theme));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ini.pretty_write(path, &qt_settings_ini_style())
|
|
||||||
.map_err(OutputError::Io)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reset the applied qt56ct config by removing COSMIC-specific entries from the config file.
|
|
||||||
#[cold]
|
|
||||||
pub fn reset_qt56ct() -> Result<(), OutputError> {
|
|
||||||
let qt5ct_res = Self::reset_ct("qt5ct");
|
|
||||||
let qt6ct_res = Self::reset_ct("qt6ct");
|
|
||||||
qt5ct_res?;
|
|
||||||
qt6ct_res?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
#[must_use]
|
|
||||||
#[cold]
|
|
||||||
fn reset_ct(ct: &str) -> Result<(), OutputError> {
|
|
||||||
let path = Self::get_conf_path(ct)?;
|
|
||||||
let file_content = fs::read_to_string(&path).map_err(OutputError::Io)?;
|
|
||||||
let mut ini = Ini::new_cs();
|
|
||||||
ini.read(file_content).map_err(OutputError::Ini)?;
|
|
||||||
|
|
||||||
let old_version = ini
|
|
||||||
.getuint("Appearance", "cosmic_qt_version")
|
|
||||||
.map_err(OutputError::Ini)?
|
|
||||||
.unwrap_or_default();
|
|
||||||
if old_version == 0 {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
ini.remove_key("Appearance", "cosmic_qt_version");
|
|
||||||
ini.remove_key("Appearance", "color_scheme_path");
|
|
||||||
ini.remove_key("Appearance", "icon_theme");
|
|
||||||
|
|
||||||
ini.pretty_write(path, &qt_settings_ini_style())
|
|
||||||
.map_err(OutputError::Io)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the file paths of the form `~/.config/ct/ct.conf`:
|
|
||||||
/// e.g. `~/.config/qt6ct/qt6ct.conf`.
|
|
||||||
///
|
|
||||||
/// The file and its parent directory are created if they don't exist.
|
|
||||||
#[cold]
|
|
||||||
fn get_conf_path(ct: &str) -> Result<PathBuf, OutputError> {
|
|
||||||
assert!(ct == "qt5ct" || ct == "qt6ct");
|
|
||||||
|
|
||||||
let Some(mut config_dir) = dirs::config_dir() else {
|
|
||||||
return Err(OutputError::MissingConfigDir);
|
|
||||||
};
|
|
||||||
config_dir.push(&ct);
|
|
||||||
if !config_dir.exists() {
|
|
||||||
fs::create_dir_all(&config_dir).map_err(OutputError::Io)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let file_path = config_dir.join(ct.to_owned() + ".conf");
|
|
||||||
if !file_path.exists() {
|
|
||||||
File::create_new(&file_path).map_err(OutputError::Io)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(file_path)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a path like `~/.config/qt6ct/colors/CosmicDark.conf`
|
|
||||||
///
|
|
||||||
/// Its parent directory is created if it doesn't exist.
|
|
||||||
#[cold]
|
|
||||||
fn get_qpalette_path(ct: &str, is_dark: bool) -> Result<PathBuf, OutputError> {
|
|
||||||
assert!(ct == "qt5ct" || ct == "qt6ct");
|
|
||||||
|
|
||||||
let Some(mut config_dir) = dirs::config_dir() else {
|
|
||||||
return Err(OutputError::MissingConfigDir);
|
|
||||||
};
|
|
||||||
config_dir.push(&ct);
|
|
||||||
config_dir.push("colors");
|
|
||||||
if !config_dir.exists() {
|
|
||||||
fs::create_dir_all(&config_dir).map_err(OutputError::Io)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let file_name = if is_dark {
|
|
||||||
"CosmicDark.conf"
|
|
||||||
} else {
|
|
||||||
"CosmicLight.conf"
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(config_dir.join(file_name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Defines the different symbolic color roles used in current GUIs.
|
|
||||||
///
|
|
||||||
/// qt5ct and qt6ct consume this as a list of colors, ordered by ColorRole:
|
|
||||||
/// - https://doc.qt.io/qt-6/qpalette.html#ColorRole-enum
|
|
||||||
/// - https://doc.qt.io/archives/qt-5.15/qpalette.html#ColorRole-enum
|
|
||||||
struct QPaletteGroup {
|
|
||||||
/// A general foreground color.
|
|
||||||
window_text: Srgba,
|
|
||||||
/// The general button background color.
|
|
||||||
button: Srgba,
|
|
||||||
/// Lighter than [button] color, used mostly for 3D bevel and shadow effects.
|
|
||||||
light: Srgba,
|
|
||||||
/// Between [button] and [light], used mostly for 3D bevel and shadow effects.
|
|
||||||
midlight: Srgba,
|
|
||||||
/// Darker than [button], used mostly for 3D bevel and shadow effects.
|
|
||||||
dark: Srgba,
|
|
||||||
/// Between [button] and [dark], used mostly for 3D bevel and shadow effects.
|
|
||||||
mid: Srgba,
|
|
||||||
/// The foreground color used with [base].
|
|
||||||
text: Srgba,
|
|
||||||
/// A text color that is very different from [window_text], and contrasts well with e.g. [dark].
|
|
||||||
/// Typically used for text that needs to be drawn where [text] or [window_text] would give poor contrast, such as on pressed push buttons.
|
|
||||||
bright_text: Srgba,
|
|
||||||
/// A foreground color used with the [button] color.
|
|
||||||
button_text: Srgba,
|
|
||||||
/// Used mostly as the background color for text entry widgets, but can also be used for other painting -
|
|
||||||
/// such as the background of combobox drop down lists and toolbar handles.
|
|
||||||
base: Srgba,
|
|
||||||
/// A general background color.
|
|
||||||
window: Srgba,
|
|
||||||
/// A very dark color, used mostly for 3D bevel and shadow effects.
|
|
||||||
/// Opaque black by default.
|
|
||||||
shadow: Srgba,
|
|
||||||
/// A color to indicate a selected item or the current item.
|
|
||||||
highlight: Srgba,
|
|
||||||
/// A text color that contrasts with [highlight].
|
|
||||||
highlighted_text: Srgba,
|
|
||||||
/// A text color used for unvisited hyperlinks.
|
|
||||||
link: Srgba,
|
|
||||||
/// A text color used for already visited hyperlinks.
|
|
||||||
link_visited: Srgba,
|
|
||||||
/// Used as the alternate background color in views with alternating row colors.
|
|
||||||
alternate_base: Srgba,
|
|
||||||
/// No role; this special role is often used to indicate that a role has not been assigned.
|
|
||||||
no_role: Srgba,
|
|
||||||
/// Used as the background color for QToolTip and QWhatsThis.
|
|
||||||
/// Tool tips use the inactive color group of QPalette, because tool tips are not active windows.
|
|
||||||
tool_tip_base: Srgba,
|
|
||||||
/// Used as the foreground color for QToolTip and QWhatsThis.
|
|
||||||
/// Tool tips use the inactive color group of QPalette, because tool tips are not active windows.
|
|
||||||
tool_tip_text: Srgba,
|
|
||||||
/// Used as the placeholder color for various text input widgets.
|
|
||||||
placeholder_text: Srgba,
|
|
||||||
// /// [accent] only exists since Qt 6.6. Including it here breaks qt5ct.
|
|
||||||
// /// When omitted, it defaults to [highlight].
|
|
||||||
// accent: Srgba,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl QPaletteGroup {
|
|
||||||
/// Returns a comma-separated list of the colors as hex codes.
|
|
||||||
/// E.g. `#ff000000, #ffdcdcdc, ...`
|
|
||||||
///
|
|
||||||
/// Any transparent colors are flattened with [base] to avoid issues with
|
|
||||||
/// the Fusion style.
|
|
||||||
fn as_list(&self) -> String {
|
|
||||||
let colors = vec![
|
|
||||||
to_argb_hex(self.window_text.over(self.base)),
|
|
||||||
to_argb_hex(self.button.over(self.base)),
|
|
||||||
to_argb_hex(self.light.over(self.base)),
|
|
||||||
to_argb_hex(self.midlight.over(self.base)),
|
|
||||||
to_argb_hex(self.dark.over(self.base)),
|
|
||||||
to_argb_hex(self.mid.over(self.base)),
|
|
||||||
to_argb_hex(self.text.over(self.base)),
|
|
||||||
to_argb_hex(self.bright_text.over(self.base)),
|
|
||||||
to_argb_hex(self.button_text.over(self.base)),
|
|
||||||
to_argb_hex(self.base.over(self.base)),
|
|
||||||
to_argb_hex(self.window.over(self.base)),
|
|
||||||
to_argb_hex(self.shadow.over(self.base)),
|
|
||||||
to_argb_hex(self.highlight.over(self.base)),
|
|
||||||
to_argb_hex(self.highlighted_text.over(self.base)),
|
|
||||||
to_argb_hex(self.link.over(self.base)),
|
|
||||||
to_argb_hex(self.link_visited.over(self.base)),
|
|
||||||
to_argb_hex(self.alternate_base.over(self.base)),
|
|
||||||
to_argb_hex(self.no_role.over(self.base)),
|
|
||||||
to_argb_hex(self.tool_tip_base.over(self.base)),
|
|
||||||
to_argb_hex(self.tool_tip_text.over(self.base)),
|
|
||||||
to_argb_hex(self.placeholder_text.over(self.base)),
|
|
||||||
];
|
|
||||||
colors.join(", ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a color to a hex string in the format `#AARRGGBB`.
|
|
||||||
/// Do not use [to_hex] since that uses the format `RRGGBBAA`.
|
|
||||||
fn to_argb_hex(c: Srgba) -> String {
|
|
||||||
let c_u8: Rgba<palette::encoding::Srgb, u8> = c.into_format();
|
|
||||||
format!(
|
|
||||||
"#{:02x}{:02x}{:02x}{:02x}",
|
|
||||||
c_u8.alpha, c_u8.red, c_u8.green, c_u8.blue
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_color_to_argb_hex() {
|
|
||||||
let color = Srgba::new(0x33, 0x55, 0x77, 0xff);
|
|
||||||
let argb = to_argb_hex(color.into());
|
|
||||||
assert_eq!(argb, "#ff335577");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_light_default_qpalette() {
|
|
||||||
let light_default_qpalette = Theme::light_default().as_qpalette();
|
|
||||||
insta::assert_snapshot!(light_default_qpalette);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_dark_default_qpalette() {
|
|
||||||
let dark_default_qpalette = Theme::dark_default().as_qpalette();
|
|
||||||
insta::assert_snapshot!(dark_default_qpalette);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,568 +0,0 @@
|
||||||
use crate::Theme;
|
|
||||||
use configparser::ini::Ini;
|
|
||||||
use cosmic_config::CosmicConfigEntry;
|
|
||||||
use palette::{Mix, Srgba, blend::Compose};
|
|
||||||
use std::{
|
|
||||||
fs::{self, File},
|
|
||||||
io::{self, Write},
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{OutputError, qt_settings_ini_style};
|
|
||||||
|
|
||||||
impl Theme {
|
|
||||||
/// Produces a color scheme ini file for Qt.
|
|
||||||
///
|
|
||||||
/// Some high-level documentation for this file can be found at:
|
|
||||||
/// - https://api.kde.org/kcolorscheme.html
|
|
||||||
/// - https://web.archive.org/web/20250402234329/https://docs.kde.org/stable5/en/plasma-workspace/kcontrol/colors/
|
|
||||||
#[must_use]
|
|
||||||
#[cold]
|
|
||||||
pub fn as_kcolorscheme(&self) -> String {
|
|
||||||
// Usually, disabled elements will have strongly reduced contrast and are often notably darker or lighter
|
|
||||||
let disabled_color_effects = IniColorEffects {
|
|
||||||
color: self.button.disabled,
|
|
||||||
color_amount: 0.0,
|
|
||||||
color_effect: ColorEffect::Desaturate,
|
|
||||||
contrast_amount: 0.65,
|
|
||||||
contrast_effect: ColorEffect::Fade,
|
|
||||||
intensity_amount: 0.1,
|
|
||||||
intensity_effect: IntensityEffect::Lighten,
|
|
||||||
};
|
|
||||||
// Usually, inactive elements will have reduced contrast (text fades slightly into the background) and may have slightly reduced intensity
|
|
||||||
let inactive_color_effects = IniColorEffects {
|
|
||||||
color: self.palette.gray_1,
|
|
||||||
color_amount: 0.025,
|
|
||||||
color_effect: ColorEffect::Tint,
|
|
||||||
contrast_amount: 0.1,
|
|
||||||
contrast_effect: ColorEffect::Tint,
|
|
||||||
intensity_amount: 0.0,
|
|
||||||
intensity_effect: IntensityEffect::Shade,
|
|
||||||
};
|
|
||||||
|
|
||||||
let bg = self.background.base;
|
|
||||||
// the background container
|
|
||||||
let window_colors = IniColors {
|
|
||||||
background_alternate: bg.mix(self.accent.base, 0.05),
|
|
||||||
background_normal: bg,
|
|
||||||
decoration_focus: self.accent_text_color(),
|
|
||||||
decoration_hover: self.accent_text_color(),
|
|
||||||
foreground_active: self.accent_text_color(),
|
|
||||||
foreground_inactive: self.background.on.mix(bg, 0.1),
|
|
||||||
foreground_link: self.link_button.on,
|
|
||||||
foreground_negative: self.destructive_text_color(),
|
|
||||||
foreground_neutral: self.warning_text_color(),
|
|
||||||
foreground_normal: self.background.on,
|
|
||||||
foreground_positive: self.success_text_color(),
|
|
||||||
foreground_visited: self.accent_text_color(),
|
|
||||||
};
|
|
||||||
// components inside the background container
|
|
||||||
let view_colors = IniColors {
|
|
||||||
background_alternate: self.background.component.base.mix(self.accent.base, 0.05),
|
|
||||||
background_normal: self.background.component.base,
|
|
||||||
..window_colors
|
|
||||||
};
|
|
||||||
|
|
||||||
// selected text and items
|
|
||||||
let selection_colors = {
|
|
||||||
// selection colors are swapped to fix menu bar contrast
|
|
||||||
let selected = self.background.component.selected_text;
|
|
||||||
let selected_text = self.background.component.selected;
|
|
||||||
IniColors {
|
|
||||||
background_alternate: selected.mix(bg, 0.5),
|
|
||||||
background_normal: selected,
|
|
||||||
decoration_focus: selected,
|
|
||||||
decoration_hover: selected,
|
|
||||||
foreground_active: selected_text,
|
|
||||||
foreground_inactive: selected_text.mix(selected, 0.5),
|
|
||||||
foreground_link: self.link_button.base,
|
|
||||||
foreground_negative: self.destructive_color(),
|
|
||||||
foreground_neutral: self.warning_color(),
|
|
||||||
foreground_normal: selected_text,
|
|
||||||
foreground_positive: self.success_color(),
|
|
||||||
foreground_visited: self.accent_color(),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let button_colors = IniColors {
|
|
||||||
background_alternate: self.accent_button.base,
|
|
||||||
background_normal: self.button.base,
|
|
||||||
..view_colors
|
|
||||||
};
|
|
||||||
|
|
||||||
// Complementary: Areas of applications with an alternative color scheme; usually with a dark background for light color schemes.
|
|
||||||
let complementary_colors = {
|
|
||||||
let dark = if self.is_dark {
|
|
||||||
self.clone()
|
|
||||||
} else if cfg!(test) {
|
|
||||||
// For reproducible results in tests, use the default dark theme
|
|
||||||
Theme::dark_default()
|
|
||||||
} else {
|
|
||||||
Theme::dark_config()
|
|
||||||
.ok()
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|conf| Theme::get_entry(conf).ok())
|
|
||||||
.unwrap_or_else(|| self.clone())
|
|
||||||
};
|
|
||||||
IniColors {
|
|
||||||
background_alternate: dark.accent.base,
|
|
||||||
background_normal: dark.background.base,
|
|
||||||
decoration_focus: dark.accent_text_color(),
|
|
||||||
decoration_hover: dark.accent_text_color(),
|
|
||||||
foreground_active: dark.accent_text_color(),
|
|
||||||
foreground_inactive: dark.background.on.mix(dark.background.base, 0.1),
|
|
||||||
foreground_link: dark.link_button.on,
|
|
||||||
foreground_negative: dark.destructive_text_color(),
|
|
||||||
foreground_neutral: dark.warning_text_color(),
|
|
||||||
foreground_normal: dark.background.on,
|
|
||||||
foreground_positive: dark.success_text_color(),
|
|
||||||
foreground_visited: dark.accent_text_color(),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// headers in cosmic don't have a background
|
|
||||||
let header_colors = &window_colors;
|
|
||||||
let header_colors_inactive = &window_colors;
|
|
||||||
// tool tips, "What's This" tips, and similar elements
|
|
||||||
let tooltip_colors = &view_colors;
|
|
||||||
|
|
||||||
let general_color_scheme = if self.is_dark {
|
|
||||||
"CosmicDark"
|
|
||||||
} else {
|
|
||||||
"CosmicLight"
|
|
||||||
};
|
|
||||||
let general_name = if self.is_dark {
|
|
||||||
"COSMIC Dark"
|
|
||||||
} else {
|
|
||||||
"COSMIC Light"
|
|
||||||
};
|
|
||||||
// COSMIC icons are stuck in light mode, so use breeze icons instead
|
|
||||||
let icons_theme = if self.is_dark {
|
|
||||||
"breeze-dark"
|
|
||||||
} else {
|
|
||||||
"breeze"
|
|
||||||
};
|
|
||||||
|
|
||||||
format!(
|
|
||||||
r#"# GENERATED BY COSMIC
|
|
||||||
|
|
||||||
[ColorEffects:Disabled]
|
|
||||||
{}
|
|
||||||
|
|
||||||
[ColorEffects:Inactive]
|
|
||||||
ChangeSelectionColor=false
|
|
||||||
Enable=false
|
|
||||||
{}
|
|
||||||
|
|
||||||
[Colors:Button]
|
|
||||||
{}
|
|
||||||
|
|
||||||
[Colors:Complementary]
|
|
||||||
{}
|
|
||||||
|
|
||||||
[Colors:Header]
|
|
||||||
{}
|
|
||||||
|
|
||||||
[Colors:Header][Inactive]
|
|
||||||
{}
|
|
||||||
|
|
||||||
[Colors:Selection]
|
|
||||||
{}
|
|
||||||
|
|
||||||
[Colors:Tooltip]
|
|
||||||
{}
|
|
||||||
|
|
||||||
[Colors:View]
|
|
||||||
{}
|
|
||||||
|
|
||||||
[Colors:Window]
|
|
||||||
{}
|
|
||||||
|
|
||||||
[General]
|
|
||||||
ColorScheme={general_color_scheme}
|
|
||||||
Name={general_name}
|
|
||||||
shadeSortColumn=true
|
|
||||||
|
|
||||||
[Icons]
|
|
||||||
Theme={icons_theme}
|
|
||||||
|
|
||||||
[KDE]
|
|
||||||
contrast=4
|
|
||||||
widgetStyle=qt6ct-style
|
|
||||||
|
|
||||||
[WM]
|
|
||||||
{}
|
|
||||||
"#,
|
|
||||||
format_ini_color_effects(&disabled_color_effects, bg),
|
|
||||||
format_ini_color_effects(&inactive_color_effects, bg),
|
|
||||||
format_ini_colors(&button_colors, bg),
|
|
||||||
format_ini_colors(&complementary_colors, bg),
|
|
||||||
format_ini_colors(&header_colors, bg),
|
|
||||||
format_ini_colors(&header_colors_inactive, bg),
|
|
||||||
format_ini_colors(&selection_colors, bg),
|
|
||||||
format_ini_colors(&tooltip_colors, bg),
|
|
||||||
format_ini_colors(&view_colors, bg),
|
|
||||||
format_ini_colors(&window_colors, bg),
|
|
||||||
format_ini_wm_colors(&window_colors, self.is_dark),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write the color scheme to the appropriate directory.
|
|
||||||
/// Should be written in `~/.local/share/color-schemes/`.
|
|
||||||
///
|
|
||||||
/// See the docs: https://develop.kde.org/docs/plasma/#color-scheme
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns an `OutputError` if there is an error writing the colors file.
|
|
||||||
#[cold]
|
|
||||||
pub fn write_qt(&self) -> Result<(), OutputError> {
|
|
||||||
let kcolorscheme = self.as_kcolorscheme();
|
|
||||||
let file_path = Self::get_kcolorscheme_path(self.is_dark)?;
|
|
||||||
let tmp_file_path = file_path.with_extension("colors.new");
|
|
||||||
|
|
||||||
// Write to tmp_file_path first, then move it to file_path
|
|
||||||
let mut tmp_file = File::create(&tmp_file_path).map_err(OutputError::Io)?;
|
|
||||||
let res = tmp_file
|
|
||||||
.write_all(kcolorscheme.as_bytes())
|
|
||||||
.and_then(|_| tmp_file.flush())
|
|
||||||
.and_then(|_| std::fs::rename(&tmp_file_path, file_path));
|
|
||||||
if let Err(e) = res {
|
|
||||||
_ = std::fs::remove_file(&tmp_file_path);
|
|
||||||
return Err(OutputError::Io(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Apply the color scheme by copying its values to `~/.config/kdeglobals`.
|
|
||||||
///
|
|
||||||
/// See the docs: https://develop.kde.org/docs/plasma/#color-scheme
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns an `OutputError` if there is an error applying the color scheme.
|
|
||||||
#[cold]
|
|
||||||
pub fn apply_qt(is_dark: bool) -> Result<(), OutputError> {
|
|
||||||
let Some(config_dir) = dirs::config_dir() else {
|
|
||||||
return Err(OutputError::MissingConfigDir);
|
|
||||||
};
|
|
||||||
let kdeglobals_file = config_dir.join("kdeglobals");
|
|
||||||
let mut kdeglobals_ini = Self::read_ini(&kdeglobals_file)?;
|
|
||||||
|
|
||||||
let src_file = Self::get_kcolorscheme_path(is_dark)?;
|
|
||||||
let src_ini = Self::read_ini(&src_file)?;
|
|
||||||
|
|
||||||
Self::backup_non_cosmic_kdeglobals(&kdeglobals_ini, &kdeglobals_file)
|
|
||||||
.map_err(OutputError::Io)?;
|
|
||||||
|
|
||||||
for (section, key_value) in src_ini.get_map_ref() {
|
|
||||||
for (key, value) in key_value {
|
|
||||||
kdeglobals_ini.set(section, key, value.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kdeglobals_ini
|
|
||||||
.pretty_write(kdeglobals_file, &qt_settings_ini_style())
|
|
||||||
.map_err(OutputError::Io)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reset the applied qt colors by removing color scheme values from the
|
|
||||||
/// `~/.config/kdeglobals` file.
|
|
||||||
///
|
|
||||||
/// This does not restore the backed up kdeglobals file.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns an `OutputError` if there is an error resetting the CSS file.
|
|
||||||
#[cold]
|
|
||||||
pub fn reset_qt() -> Result<(), OutputError> {
|
|
||||||
let Some(config_dir) = dirs::config_dir() else {
|
|
||||||
return Err(OutputError::MissingConfigDir);
|
|
||||||
};
|
|
||||||
let kdeglobals_file = config_dir.join("kdeglobals");
|
|
||||||
let mut kdeglobals_ini = Self::read_ini(&kdeglobals_file)?;
|
|
||||||
|
|
||||||
if !Self::is_cosmic_kdeglobals(&kdeglobals_ini)
|
|
||||||
.map_err(OutputError::Io)?
|
|
||||||
.unwrap_or_default()
|
|
||||||
{
|
|
||||||
// Not a cosmic kdeglobals file, do nothing
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let is_dark = false; // doesn't matter since we're only reading keys
|
|
||||||
let src_file = Self::get_kcolorscheme_path(is_dark)?;
|
|
||||||
let src_ini = Self::read_ini(&src_file)?;
|
|
||||||
|
|
||||||
for (section, key_value) in src_ini.get_map_ref() {
|
|
||||||
for (key, _) in key_value {
|
|
||||||
kdeglobals_ini.remove_key(section, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kdeglobals_ini
|
|
||||||
.write(kdeglobals_file)
|
|
||||||
.map_err(OutputError::Io)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a path like `~/.local/share/color-schemes/CosmicDark.colors`
|
|
||||||
fn get_kcolorscheme_path(is_dark: bool) -> Result<PathBuf, OutputError> {
|
|
||||||
let Some(mut data_dir) = dirs::data_dir() else {
|
|
||||||
return Err(OutputError::MissingDataDir);
|
|
||||||
};
|
|
||||||
|
|
||||||
let file_name = if is_dark {
|
|
||||||
"CosmicDark.colors"
|
|
||||||
} else {
|
|
||||||
"CosmicLight.colors"
|
|
||||||
};
|
|
||||||
|
|
||||||
data_dir.push("color-schemes");
|
|
||||||
if !data_dir.exists() {
|
|
||||||
std::fs::create_dir_all(&data_dir).map_err(OutputError::Io)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(data_dir.join(file_name))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cold]
|
|
||||||
fn read_ini(path: &PathBuf) -> Result<Ini, OutputError> {
|
|
||||||
let mut ini = Ini::new_cs();
|
|
||||||
if !path.exists() {
|
|
||||||
return Ok(ini);
|
|
||||||
}
|
|
||||||
let file_content = fs::read_to_string(path).map_err(OutputError::Io)?;
|
|
||||||
ini.read(file_content).map_err(OutputError::Ini)?;
|
|
||||||
Ok(ini)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cold]
|
|
||||||
fn backup_non_cosmic_kdeglobals(ini: &Ini, path: &Path) -> io::Result<()> {
|
|
||||||
if !Self::is_cosmic_kdeglobals(&ini)?.unwrap_or(true) {
|
|
||||||
let backup_path = path.with_extension("bak");
|
|
||||||
fs::copy(path, &backup_path)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cold]
|
|
||||||
fn is_cosmic_kdeglobals(ini: &Ini) -> io::Result<Option<bool>> {
|
|
||||||
let color_scheme = ini.get("General", "ColorScheme");
|
|
||||||
if let Some(color_scheme) = color_scheme {
|
|
||||||
Ok(Some(
|
|
||||||
color_scheme == "CosmicDark" || color_scheme == "CosmicLight",
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Formats a color in the form `r,g,b` e.g. `255,255,255`.
|
|
||||||
/// If the color has transparency, it is mixed with bg first.
|
|
||||||
fn to_rgb(c: Srgba, bg: Srgba) -> String {
|
|
||||||
let c_u8: Srgba<u8> = c.over(bg).into_format();
|
|
||||||
format!("{},{},{}", c_u8.red, c_u8.green, c_u8.blue)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn format_ini_color_effects(color_effects: &IniColorEffects, bg: Srgba) -> String {
|
|
||||||
format!(
|
|
||||||
r#"Color={}
|
|
||||||
ColorAmount={}
|
|
||||||
ColorEffect={}
|
|
||||||
ContrastAmount={}
|
|
||||||
ContrastEffect={}
|
|
||||||
IntensityAmount={}
|
|
||||||
IntensityEffect={}"#,
|
|
||||||
to_rgb(color_effects.color, bg),
|
|
||||||
color_effects.color_amount,
|
|
||||||
color_effects.color_effect.as_u8(),
|
|
||||||
color_effects.contrast_amount,
|
|
||||||
color_effects.contrast_effect.as_u8(),
|
|
||||||
color_effects.intensity_amount,
|
|
||||||
color_effects.intensity_effect.as_u8(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn format_ini_colors(colors: &IniColors, bg: Srgba) -> String {
|
|
||||||
format!(
|
|
||||||
r#"BackgroundAlternate={}
|
|
||||||
BackgroundNormal={}
|
|
||||||
DecorationFocus={}
|
|
||||||
DecorationHover={}
|
|
||||||
ForegroundActive={}
|
|
||||||
ForegroundInactive={}
|
|
||||||
ForegroundLink={}
|
|
||||||
ForegroundNegative={}
|
|
||||||
ForegroundNeutral={}
|
|
||||||
ForegroundNormal={}
|
|
||||||
ForegroundPositive={}
|
|
||||||
ForegroundVisited={}"#,
|
|
||||||
to_rgb(colors.background_alternate, bg),
|
|
||||||
to_rgb(colors.background_normal, bg),
|
|
||||||
to_rgb(colors.decoration_focus, bg),
|
|
||||||
to_rgb(colors.decoration_hover, bg),
|
|
||||||
to_rgb(colors.foreground_active, bg),
|
|
||||||
to_rgb(colors.foreground_inactive, bg),
|
|
||||||
to_rgb(colors.foreground_link, bg),
|
|
||||||
to_rgb(colors.foreground_negative, bg),
|
|
||||||
to_rgb(colors.foreground_neutral, bg),
|
|
||||||
to_rgb(colors.foreground_normal, bg),
|
|
||||||
to_rgb(colors.foreground_positive, bg),
|
|
||||||
to_rgb(colors.foreground_visited, bg),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the colors for the titlebars of active and inactive windows.
|
|
||||||
fn format_ini_wm_colors(view_colors: &IniColors, is_dark: bool) -> String {
|
|
||||||
let bg = view_colors.background_normal;
|
|
||||||
let fg = view_colors.foreground_active;
|
|
||||||
let blend = if is_dark { fg } else { bg };
|
|
||||||
|
|
||||||
format!(
|
|
||||||
r#"activeBackground={}
|
|
||||||
activeBlend={}
|
|
||||||
activeForeground={}
|
|
||||||
inactiveBackground={}
|
|
||||||
inactiveBlend={}
|
|
||||||
inactiveForeground={}"#,
|
|
||||||
to_rgb(bg, bg),
|
|
||||||
to_rgb(blend, bg),
|
|
||||||
to_rgb(fg, bg),
|
|
||||||
to_rgb(bg, bg),
|
|
||||||
to_rgb(blend, bg),
|
|
||||||
to_rgb(fg, bg),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct IniColorEffects {
|
|
||||||
color: Srgba,
|
|
||||||
color_amount: f32,
|
|
||||||
color_effect: ColorEffect,
|
|
||||||
contrast_amount: f32,
|
|
||||||
/// Applied to the text, using the background as the reference color.
|
|
||||||
contrast_effect: ColorEffect,
|
|
||||||
intensity_amount: f32,
|
|
||||||
intensity_effect: IntensityEffect,
|
|
||||||
}
|
|
||||||
/// Each color set is made up of a number of roles which are available in all other sets.
|
|
||||||
/// In addition, except for Inactive Text, there is a corresponding background role for each of the text roles. Currently (except for Normal and Alternate Background), these colors are not chosen here but are automatically determined based on Normal Background and the corresponding Text color.
|
|
||||||
struct IniColors {
|
|
||||||
/// used when there is a need to subtly change the background to aid in item association. This might be used e.g. as the background of a heading, but is mostly used for alternating rows in lists, especially multi-column lists, to aid in visually tracking rows.
|
|
||||||
background_alternate: Srgba,
|
|
||||||
/// Normal background
|
|
||||||
background_normal: Srgba,
|
|
||||||
/// Used for drawing lines or shading UI elements to indicate the item which has active input focus.
|
|
||||||
/// Typically the same as foreground_active.
|
|
||||||
decoration_focus: Srgba,
|
|
||||||
/// Used for drawing lines or shading UI elements for mouse-over effects, e.g. the "illumination" effects for buttons.
|
|
||||||
/// Typically the same as foreground_active.
|
|
||||||
decoration_hover: Srgba,
|
|
||||||
/// used to indicate an active element or attract attention, e.g. alerts, notifications; also for hovered hyperlinks
|
|
||||||
foreground_active: Srgba,
|
|
||||||
/// used for text which should be unobtrusive, e.g. comments, "subtitles", unimportant information, etc.
|
|
||||||
foreground_inactive: Srgba,
|
|
||||||
/// used for hyperlinks or to otherwise indicate "something which may be visited", or to show relationships
|
|
||||||
foreground_link: Srgba,
|
|
||||||
/// used for errors, failure notices, notifications that an action may be dangerous (e.g. unsafe web page or security context), etc.
|
|
||||||
foreground_negative: Srgba,
|
|
||||||
/// used to draw attention when another role is not appropriate; e.g. warnings, to indicate secure/encrypted content, etc.
|
|
||||||
foreground_neutral: Srgba,
|
|
||||||
/// Normal foreground
|
|
||||||
foreground_normal: Srgba,
|
|
||||||
/// used for success notices, to indicate trusted content, etc.
|
|
||||||
foreground_positive: Srgba,
|
|
||||||
/// used for "something (e.g. a hyperlink) that has been visited", or to indicate something that is "old".
|
|
||||||
foreground_visited: Srgba,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Intensity allows the overall color to be lightened or darkened.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
enum IntensityEffect {
|
|
||||||
/// Makes everything lighter or darker in a controlled manner.
|
|
||||||
///
|
|
||||||
/// intensity_amount increases or decreases the overall intensity (i.e. perceived brightness) by an absolute amount.
|
|
||||||
Shade,
|
|
||||||
/// Changes the intensity to a percentage of the initial value.
|
|
||||||
Darken,
|
|
||||||
/// Conceptually the opposite of darken; lighten can be thought of as working with "distance from white", where darken works with "distance from black".
|
|
||||||
Lighten,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntensityEffect {
|
|
||||||
pub fn as_u8(&self) -> u8 {
|
|
||||||
match self {
|
|
||||||
Self::Shade => 0,
|
|
||||||
Self::Darken => 1,
|
|
||||||
Self::Lighten => 2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This also changes the overall color like [IntensityEffect],
|
|
||||||
/// but is not limited to intensity.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
enum ColorEffect {
|
|
||||||
/// changes the relative chroma
|
|
||||||
///
|
|
||||||
/// This is available for "ColorEffect" but not "ContrastEffect".
|
|
||||||
Desaturate,
|
|
||||||
/// smoothly blends the original color into a reference color
|
|
||||||
Fade,
|
|
||||||
/// similar to Fade, except that the color (hue and chroma) changes more quickly while the intensity changes more slowly as the amount is increased
|
|
||||||
Tint,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ColorEffect {
|
|
||||||
pub fn as_u8(&self) -> u8 {
|
|
||||||
match self {
|
|
||||||
Self::Desaturate => 0,
|
|
||||||
Self::Fade => 1,
|
|
||||||
Self::Tint => 2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_opaque_color_to_rgb() {
|
|
||||||
let color = Srgba::new(30.0 / 255.0, 50.0 / 255.0, 70.0 / 255.0, 1.0);
|
|
||||||
let bg = Srgba::new(1.0, 1.0, 1.0, 1.0);
|
|
||||||
let result = to_rgb(color, bg);
|
|
||||||
assert_eq!(result, "30,50,70");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_transparent_color_to_rgb() {
|
|
||||||
let color = Srgba::new(0.0, 0.0, 0.0, 0.0);
|
|
||||||
let bg = Srgba::new(1.0, 1.0, 1.0, 1.0);
|
|
||||||
let result = to_rgb(color, bg);
|
|
||||||
assert_eq!(result, "255,255,255");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_translucent_color_to_rgb() {
|
|
||||||
let color = Srgba::new(0.0, 0.0, 0.0, 0.9);
|
|
||||||
let bg = Srgba::new(1.0, 1.0, 1.0, 1.0);
|
|
||||||
let result = to_rgb(color, bg);
|
|
||||||
assert_eq!(result, "26,26,26");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_light_default_kcolorscheme() {
|
|
||||||
let light_default_kcolorscheme = Theme::light_default().as_kcolorscheme();
|
|
||||||
insta::assert_snapshot!(light_default_kcolorscheme);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_dark_default_kcolorscheme() {
|
|
||||||
let dark_default_kcolorscheme = Theme::dark_default().as_kcolorscheme();
|
|
||||||
insta::assert_snapshot!(dark_default_kcolorscheme);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
---
|
|
||||||
source: cosmic-theme/src/output/qt56ct_output.rs
|
|
||||||
expression: dark_default_qpalette
|
|
||||||
---
|
|
||||||
# GENERATED BY COSMIC
|
|
||||||
|
|
||||||
[ColorScheme]
|
|
||||||
active_colors=#ffe7e7e7, #ff4a4a4a, #ff555555, #ff505050, #ff4f4f4f, #ff4d4d4d, #ffc0c0c0, #ffe7e7e7, #ffc0c0c0, #ff2e2e2e, #ff1b1b1b, #ff1b1b1b, #ff63d0df, #ff434343, #ff63d0df, #ff5bb2be, #ff1f2425, #ff2e2e2e, #ff2e2e2e, #ffc0c0c0, #ff777777
|
|
||||||
disabled_colors=#e6d3d3d3, #8f474747, #a9696969, #a4626262, #a95f5f5f, #a45d5d5d, #d2a1a1a1, #ffe7e7e7, #d2a1a1a1, #bf2e2e2e, #ff1b1b1b, #ff1b1b1b, #ff63d0df, #bf3c3c3c, #bf30555a, #bf324f53, #ff1f2425, #bf2e2e2e, #bf2e2e2e, #d2a1a1a1, #bf909090
|
|
||||||
inactive_colors=#ffc2c2c2, #ff4a4a4a, #ff555555, #ff505050, #ff4f4f4f, #ff4d4d4d, #ffa3a3a3, #ffe7e7e7, #ffc0c0c0, #ff2e2e2e, #ff1b1b1b, #ff1b1b1b, #ff63d0df, #ff3f3f3f, #ff63d0df, #ff5bb2be, #ff1f2425, #ff2e2e2e, #ff2e2e2e, #ffa3a3a3, #ff777777
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
---
|
|
||||||
source: cosmic-theme/src/output/qt56ct_output.rs
|
|
||||||
expression: light_default_qpalette
|
|
||||||
---
|
|
||||||
# GENERATED BY COSMIC
|
|
||||||
|
|
||||||
[ColorScheme]
|
|
||||||
active_colors=#ff121212, #ffc3c3c3, #ffbababa, #ffbebebe, #ffb3b3b3, #ffbbbbbb, #ff272727, #ffd7d7d7, #ff272727, #fff5f5f5, #ffd7d7d7, #ff121212, #ff00525a, #fff6f6f6, #ff00525a, #ff317379, #ffccd0d1, #fff5f5f5, #fff5f5f5, #ff272727, #ff8e8e8e
|
|
||||||
disabled_colors=#e62b2b2b, #8fc9c9c9, #a99b9b9b, #a4a0a0a0, #a9929292, #a49b9b9b, #d2535353, #ffd7d7d7, #d2535353, #bff5f5f5, #ffd7d7d7, #ff121212, #ff00525a, #bff6f6f6, #bf526d70, #bf72888a, #ffccd0d1, #bff5f5f5, #bff5f5f5, #d2535353, #bf6c6c6c
|
|
||||||
inactive_colors=#ff3f3f3f, #ffc3c3c3, #ffbababa, #ffbebebe, #ffb3b3b3, #ffbbbbbb, #ff505050, #ffd7d7d7, #ff272727, #fff5f5f5, #ffd7d7d7, #ff121212, #ff00525a, #fff6f6f6, #ff00525a, #ff317379, #ffccd0d1, #fff5f5f5, #fff5f5f5, #ff505050, #ff8e8e8e
|
|
||||||
|
|
@ -1,157 +0,0 @@
|
||||||
---
|
|
||||||
source: cosmic-theme/src/output/qt_output.rs
|
|
||||||
expression: dark_default_kcolorscheme
|
|
||||||
---
|
|
||||||
# GENERATED BY COSMIC
|
|
||||||
|
|
||||||
[ColorEffects:Disabled]
|
|
||||||
Color=43,43,43
|
|
||||||
ColorAmount=0
|
|
||||||
ColorEffect=0
|
|
||||||
ContrastAmount=0.65
|
|
||||||
ContrastEffect=1
|
|
||||||
IntensityAmount=0.1
|
|
||||||
IntensityEffect=2
|
|
||||||
|
|
||||||
[ColorEffects:Inactive]
|
|
||||||
ChangeSelectionColor=false
|
|
||||||
Enable=false
|
|
||||||
Color=27,27,27
|
|
||||||
ColorAmount=0.025
|
|
||||||
ColorEffect=2
|
|
||||||
ContrastAmount=0.1
|
|
||||||
ContrastEffect=2
|
|
||||||
IntensityAmount=0
|
|
||||||
IntensityEffect=0
|
|
||||||
|
|
||||||
[Colors:Button]
|
|
||||||
BackgroundAlternate=99,208,223
|
|
||||||
BackgroundNormal=60,60,60
|
|
||||||
DecorationFocus=99,208,223
|
|
||||||
DecorationHover=99,208,223
|
|
||||||
ForegroundActive=99,208,223
|
|
||||||
ForegroundInactive=211,211,211
|
|
||||||
ForegroundLink=99,208,223
|
|
||||||
ForegroundNegative=255,160,154
|
|
||||||
ForegroundNeutral=255,163,125
|
|
||||||
ForegroundNormal=231,231,231
|
|
||||||
ForegroundPositive=94,219,140
|
|
||||||
ForegroundVisited=99,208,223
|
|
||||||
|
|
||||||
[Colors:Complementary]
|
|
||||||
BackgroundAlternate=99,208,223
|
|
||||||
BackgroundNormal=27,27,27
|
|
||||||
DecorationFocus=99,208,223
|
|
||||||
DecorationHover=99,208,223
|
|
||||||
ForegroundActive=99,208,223
|
|
||||||
ForegroundInactive=211,211,211
|
|
||||||
ForegroundLink=99,208,223
|
|
||||||
ForegroundNegative=255,160,154
|
|
||||||
ForegroundNeutral=255,163,125
|
|
||||||
ForegroundNormal=231,231,231
|
|
||||||
ForegroundPositive=94,219,140
|
|
||||||
ForegroundVisited=99,208,223
|
|
||||||
|
|
||||||
[Colors:Header]
|
|
||||||
BackgroundAlternate=31,36,37
|
|
||||||
BackgroundNormal=27,27,27
|
|
||||||
DecorationFocus=99,208,223
|
|
||||||
DecorationHover=99,208,223
|
|
||||||
ForegroundActive=99,208,223
|
|
||||||
ForegroundInactive=211,211,211
|
|
||||||
ForegroundLink=99,208,223
|
|
||||||
ForegroundNegative=255,160,154
|
|
||||||
ForegroundNeutral=255,163,125
|
|
||||||
ForegroundNormal=231,231,231
|
|
||||||
ForegroundPositive=94,219,140
|
|
||||||
ForegroundVisited=99,208,223
|
|
||||||
|
|
||||||
[Colors:Header][Inactive]
|
|
||||||
BackgroundAlternate=31,36,37
|
|
||||||
BackgroundNormal=27,27,27
|
|
||||||
DecorationFocus=99,208,223
|
|
||||||
DecorationHover=99,208,223
|
|
||||||
ForegroundActive=99,208,223
|
|
||||||
ForegroundInactive=211,211,211
|
|
||||||
ForegroundLink=99,208,223
|
|
||||||
ForegroundNegative=255,160,154
|
|
||||||
ForegroundNeutral=255,163,125
|
|
||||||
ForegroundNormal=231,231,231
|
|
||||||
ForegroundPositive=94,219,140
|
|
||||||
ForegroundVisited=99,208,223
|
|
||||||
|
|
||||||
[Colors:Selection]
|
|
||||||
BackgroundAlternate=63,118,125
|
|
||||||
BackgroundNormal=99,208,223
|
|
||||||
DecorationFocus=99,208,223
|
|
||||||
DecorationHover=99,208,223
|
|
||||||
ForegroundActive=67,67,67
|
|
||||||
ForegroundInactive=83,138,145
|
|
||||||
ForegroundLink=27,27,27
|
|
||||||
ForegroundNegative=255,160,154
|
|
||||||
ForegroundNeutral=255,163,125
|
|
||||||
ForegroundNormal=67,67,67
|
|
||||||
ForegroundPositive=94,219,140
|
|
||||||
ForegroundVisited=99,208,223
|
|
||||||
|
|
||||||
[Colors:Tooltip]
|
|
||||||
BackgroundAlternate=49,55,55
|
|
||||||
BackgroundNormal=46,46,46
|
|
||||||
DecorationFocus=99,208,223
|
|
||||||
DecorationHover=99,208,223
|
|
||||||
ForegroundActive=99,208,223
|
|
||||||
ForegroundInactive=211,211,211
|
|
||||||
ForegroundLink=99,208,223
|
|
||||||
ForegroundNegative=255,160,154
|
|
||||||
ForegroundNeutral=255,163,125
|
|
||||||
ForegroundNormal=231,231,231
|
|
||||||
ForegroundPositive=94,219,140
|
|
||||||
ForegroundVisited=99,208,223
|
|
||||||
|
|
||||||
[Colors:View]
|
|
||||||
BackgroundAlternate=49,55,55
|
|
||||||
BackgroundNormal=46,46,46
|
|
||||||
DecorationFocus=99,208,223
|
|
||||||
DecorationHover=99,208,223
|
|
||||||
ForegroundActive=99,208,223
|
|
||||||
ForegroundInactive=211,211,211
|
|
||||||
ForegroundLink=99,208,223
|
|
||||||
ForegroundNegative=255,160,154
|
|
||||||
ForegroundNeutral=255,163,125
|
|
||||||
ForegroundNormal=231,231,231
|
|
||||||
ForegroundPositive=94,219,140
|
|
||||||
ForegroundVisited=99,208,223
|
|
||||||
|
|
||||||
[Colors:Window]
|
|
||||||
BackgroundAlternate=31,36,37
|
|
||||||
BackgroundNormal=27,27,27
|
|
||||||
DecorationFocus=99,208,223
|
|
||||||
DecorationHover=99,208,223
|
|
||||||
ForegroundActive=99,208,223
|
|
||||||
ForegroundInactive=211,211,211
|
|
||||||
ForegroundLink=99,208,223
|
|
||||||
ForegroundNegative=255,160,154
|
|
||||||
ForegroundNeutral=255,163,125
|
|
||||||
ForegroundNormal=231,231,231
|
|
||||||
ForegroundPositive=94,219,140
|
|
||||||
ForegroundVisited=99,208,223
|
|
||||||
|
|
||||||
[General]
|
|
||||||
ColorScheme=CosmicDark
|
|
||||||
Name=COSMIC Dark
|
|
||||||
shadeSortColumn=true
|
|
||||||
|
|
||||||
[Icons]
|
|
||||||
Theme=breeze-dark
|
|
||||||
|
|
||||||
[KDE]
|
|
||||||
contrast=4
|
|
||||||
widgetStyle=qt6ct-style
|
|
||||||
|
|
||||||
[WM]
|
|
||||||
activeBackground=27,27,27
|
|
||||||
activeBlend=99,208,223
|
|
||||||
activeForeground=99,208,223
|
|
||||||
inactiveBackground=27,27,27
|
|
||||||
inactiveBlend=99,208,223
|
|
||||||
inactiveForeground=99,208,223
|
|
||||||
|
|
@ -1,157 +0,0 @@
|
||||||
---
|
|
||||||
source: cosmic-theme/src/output/qt_output.rs
|
|
||||||
expression: light_default_kcolorscheme
|
|
||||||
---
|
|
||||||
# GENERATED BY COSMIC
|
|
||||||
|
|
||||||
[ColorEffects:Disabled]
|
|
||||||
Color=194,194,194
|
|
||||||
ColorAmount=0
|
|
||||||
ColorEffect=0
|
|
||||||
ContrastAmount=0.65
|
|
||||||
ContrastEffect=1
|
|
||||||
IntensityAmount=0.1
|
|
||||||
IntensityEffect=2
|
|
||||||
|
|
||||||
[ColorEffects:Inactive]
|
|
||||||
ChangeSelectionColor=false
|
|
||||||
Enable=false
|
|
||||||
Color=215,215,215
|
|
||||||
ColorAmount=0.025
|
|
||||||
ColorEffect=2
|
|
||||||
ContrastAmount=0.1
|
|
||||||
ContrastEffect=2
|
|
||||||
IntensityAmount=0
|
|
||||||
IntensityEffect=0
|
|
||||||
|
|
||||||
[Colors:Button]
|
|
||||||
BackgroundAlternate=0,82,90
|
|
||||||
BackgroundNormal=173,173,173
|
|
||||||
DecorationFocus=0,82,90
|
|
||||||
DecorationHover=0,82,90
|
|
||||||
ForegroundActive=0,82,90
|
|
||||||
ForegroundInactive=38,38,38
|
|
||||||
ForegroundLink=0,82,90
|
|
||||||
ForegroundNegative=137,4,24
|
|
||||||
ForegroundNeutral=121,44,0
|
|
||||||
ForegroundNormal=18,18,18
|
|
||||||
ForegroundPositive=0,87,44
|
|
||||||
ForegroundVisited=0,82,90
|
|
||||||
|
|
||||||
[Colors:Complementary]
|
|
||||||
BackgroundAlternate=99,208,223
|
|
||||||
BackgroundNormal=27,27,27
|
|
||||||
DecorationFocus=99,208,223
|
|
||||||
DecorationHover=99,208,223
|
|
||||||
ForegroundActive=99,208,223
|
|
||||||
ForegroundInactive=211,211,211
|
|
||||||
ForegroundLink=99,208,223
|
|
||||||
ForegroundNegative=255,160,154
|
|
||||||
ForegroundNeutral=255,163,125
|
|
||||||
ForegroundNormal=231,231,231
|
|
||||||
ForegroundPositive=94,219,140
|
|
||||||
ForegroundVisited=99,208,223
|
|
||||||
|
|
||||||
[Colors:Header]
|
|
||||||
BackgroundAlternate=204,208,209
|
|
||||||
BackgroundNormal=215,215,215
|
|
||||||
DecorationFocus=0,82,90
|
|
||||||
DecorationHover=0,82,90
|
|
||||||
ForegroundActive=0,82,90
|
|
||||||
ForegroundInactive=38,38,38
|
|
||||||
ForegroundLink=0,82,90
|
|
||||||
ForegroundNegative=137,4,24
|
|
||||||
ForegroundNeutral=121,44,0
|
|
||||||
ForegroundNormal=18,18,18
|
|
||||||
ForegroundPositive=0,87,44
|
|
||||||
ForegroundVisited=0,82,90
|
|
||||||
|
|
||||||
[Colors:Header][Inactive]
|
|
||||||
BackgroundAlternate=204,208,209
|
|
||||||
BackgroundNormal=215,215,215
|
|
||||||
DecorationFocus=0,82,90
|
|
||||||
DecorationHover=0,82,90
|
|
||||||
ForegroundActive=0,82,90
|
|
||||||
ForegroundInactive=38,38,38
|
|
||||||
ForegroundLink=0,82,90
|
|
||||||
ForegroundNegative=137,4,24
|
|
||||||
ForegroundNeutral=121,44,0
|
|
||||||
ForegroundNormal=18,18,18
|
|
||||||
ForegroundPositive=0,87,44
|
|
||||||
ForegroundVisited=0,82,90
|
|
||||||
|
|
||||||
[Colors:Selection]
|
|
||||||
BackgroundAlternate=108,149,152
|
|
||||||
BackgroundNormal=0,82,90
|
|
||||||
DecorationFocus=0,82,90
|
|
||||||
DecorationHover=0,82,90
|
|
||||||
ForegroundActive=246,246,246
|
|
||||||
ForegroundInactive=123,164,168
|
|
||||||
ForegroundLink=215,215,215
|
|
||||||
ForegroundNegative=137,4,24
|
|
||||||
ForegroundNeutral=121,44,0
|
|
||||||
ForegroundNormal=246,246,246
|
|
||||||
ForegroundPositive=0,87,44
|
|
||||||
ForegroundVisited=0,82,90
|
|
||||||
|
|
||||||
[Colors:Tooltip]
|
|
||||||
BackgroundAlternate=233,237,237
|
|
||||||
BackgroundNormal=245,245,245
|
|
||||||
DecorationFocus=0,82,90
|
|
||||||
DecorationHover=0,82,90
|
|
||||||
ForegroundActive=0,82,90
|
|
||||||
ForegroundInactive=38,38,38
|
|
||||||
ForegroundLink=0,82,90
|
|
||||||
ForegroundNegative=137,4,24
|
|
||||||
ForegroundNeutral=121,44,0
|
|
||||||
ForegroundNormal=18,18,18
|
|
||||||
ForegroundPositive=0,87,44
|
|
||||||
ForegroundVisited=0,82,90
|
|
||||||
|
|
||||||
[Colors:View]
|
|
||||||
BackgroundAlternate=233,237,237
|
|
||||||
BackgroundNormal=245,245,245
|
|
||||||
DecorationFocus=0,82,90
|
|
||||||
DecorationHover=0,82,90
|
|
||||||
ForegroundActive=0,82,90
|
|
||||||
ForegroundInactive=38,38,38
|
|
||||||
ForegroundLink=0,82,90
|
|
||||||
ForegroundNegative=137,4,24
|
|
||||||
ForegroundNeutral=121,44,0
|
|
||||||
ForegroundNormal=18,18,18
|
|
||||||
ForegroundPositive=0,87,44
|
|
||||||
ForegroundVisited=0,82,90
|
|
||||||
|
|
||||||
[Colors:Window]
|
|
||||||
BackgroundAlternate=204,208,209
|
|
||||||
BackgroundNormal=215,215,215
|
|
||||||
DecorationFocus=0,82,90
|
|
||||||
DecorationHover=0,82,90
|
|
||||||
ForegroundActive=0,82,90
|
|
||||||
ForegroundInactive=38,38,38
|
|
||||||
ForegroundLink=0,82,90
|
|
||||||
ForegroundNegative=137,4,24
|
|
||||||
ForegroundNeutral=121,44,0
|
|
||||||
ForegroundNormal=18,18,18
|
|
||||||
ForegroundPositive=0,87,44
|
|
||||||
ForegroundVisited=0,82,90
|
|
||||||
|
|
||||||
[General]
|
|
||||||
ColorScheme=CosmicLight
|
|
||||||
Name=COSMIC Light
|
|
||||||
shadeSortColumn=true
|
|
||||||
|
|
||||||
[Icons]
|
|
||||||
Theme=breeze
|
|
||||||
|
|
||||||
[KDE]
|
|
||||||
contrast=4
|
|
||||||
widgetStyle=qt6ct-style
|
|
||||||
|
|
||||||
[WM]
|
|
||||||
activeBackground=215,215,215
|
|
||||||
activeBlend=215,215,215
|
|
||||||
activeForeground=0,82,90
|
|
||||||
inactiveBackground=215,215,215
|
|
||||||
inactiveBlend=215,215,215
|
|
||||||
inactiveForeground=0,82,90
|
|
||||||
|
|
@ -1,312 +0,0 @@
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::Theme;
|
|
||||||
|
|
||||||
use super::{OutputError, to_hex};
|
|
||||||
|
|
||||||
/// Represents the workbench.colorCustomizations section of a VS Code settings.json file
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct VsTheme {
|
|
||||||
#[serde(rename = "editor.background")]
|
|
||||||
editor_background: String,
|
|
||||||
#[serde(rename = "sideBar.background")]
|
|
||||||
sidebar_background: String,
|
|
||||||
#[serde(rename = "activityBar.background")]
|
|
||||||
activity_bar_background: String,
|
|
||||||
#[serde(rename = "notificationCenterHeader.background")]
|
|
||||||
notification_center_header_background: String,
|
|
||||||
#[serde(rename = "notifications.background")]
|
|
||||||
notifications_background: String,
|
|
||||||
#[serde(rename = "activityBarTop.activeBackground")]
|
|
||||||
activity_bar_top_active_background: String,
|
|
||||||
#[serde(rename = "editorGroupHeader.tabsBackground")]
|
|
||||||
editor_group_header_tabs_background: String,
|
|
||||||
#[serde(rename = "editorGroupHeader.noTabsBackground")]
|
|
||||||
editor_group_header_no_tabs_background: String,
|
|
||||||
#[serde(rename = "titleBar.activeBackground")]
|
|
||||||
title_bar_active_background: String,
|
|
||||||
#[serde(rename = "titleBar.inactiveBackground")]
|
|
||||||
title_bar_inactive_background: String,
|
|
||||||
#[serde(rename = "statusBar.background")]
|
|
||||||
status_bar_background: String,
|
|
||||||
#[serde(rename = "statusBar.noFolderBackground")]
|
|
||||||
status_bar_no_folder_background: String,
|
|
||||||
#[serde(rename = "statusBar.debuggingBackground")]
|
|
||||||
status_bar_debugging_background: String,
|
|
||||||
#[serde(rename = "tab.activeBackground")]
|
|
||||||
tab_active_background: String,
|
|
||||||
#[serde(rename = "tab.activeBorder")]
|
|
||||||
tab_active_border: String,
|
|
||||||
#[serde(rename = "tab.activeBorderTop")]
|
|
||||||
tab_active_border_top: String,
|
|
||||||
#[serde(rename = "tab.hoverBackground")]
|
|
||||||
tab_hover_background: String,
|
|
||||||
#[serde(rename = "quickInput.background")]
|
|
||||||
quick_input_background: String,
|
|
||||||
#[serde(rename = "tab.inactiveBackground")]
|
|
||||||
tab_inactive_background: String,
|
|
||||||
#[serde(rename = "sideBarSectionHeader.background")]
|
|
||||||
side_bar_section_header_background: String,
|
|
||||||
#[serde(rename = "list.focusOutline")]
|
|
||||||
list_focus_outline: String,
|
|
||||||
#[serde(rename = "banner.background")]
|
|
||||||
banner_background: String,
|
|
||||||
#[serde(rename = "breadcrumb.background")]
|
|
||||||
breadcrumb_background: String,
|
|
||||||
#[serde(rename = "commandCenter.background")]
|
|
||||||
command_center_background: String,
|
|
||||||
#[serde(rename = "terminal.background")]
|
|
||||||
terminal_background: String,
|
|
||||||
#[serde(rename = "menu.background")]
|
|
||||||
menu_background: String,
|
|
||||||
#[serde(rename = "panel.background")]
|
|
||||||
panel_background: String,
|
|
||||||
#[serde(rename = "peekViewEditorGutter.background")]
|
|
||||||
peek_view_editor_gutter_background: String,
|
|
||||||
#[serde(rename = "peekViewResult.background")]
|
|
||||||
peek_view_result_background: String,
|
|
||||||
#[serde(rename = "peekViewTitle.background")]
|
|
||||||
peek_view_title_background: String,
|
|
||||||
#[serde(rename = "peekViewEditor.background")]
|
|
||||||
peek_view_editor_background: String,
|
|
||||||
#[serde(rename = "peekViewResult.selectionBackground")]
|
|
||||||
peek_view_result_selection_background: String,
|
|
||||||
#[serde(rename = "editorWidget.background")]
|
|
||||||
editor_widget_background: String,
|
|
||||||
#[serde(rename = "editorSuggestWidget.background")]
|
|
||||||
editor_suggest_widget_background: String,
|
|
||||||
#[serde(rename = "editorHoverWidget.background")]
|
|
||||||
editor_hover_widget_background: String,
|
|
||||||
#[serde(rename = "input.background")]
|
|
||||||
input_background: String,
|
|
||||||
#[serde(rename = "dropdown.background")]
|
|
||||||
dropdown_background: String,
|
|
||||||
#[serde(rename = "settings.checkboxBackground")]
|
|
||||||
settings_checkbox_background: String,
|
|
||||||
#[serde(rename = "settings.textInputBackground")]
|
|
||||||
settings_text_input_background: String,
|
|
||||||
#[serde(rename = "settings.numberInputBackground")]
|
|
||||||
settings_number_input_background: String,
|
|
||||||
#[serde(rename = "settings.dropdownBackground")]
|
|
||||||
settings_dropdown_background: String,
|
|
||||||
#[serde(rename = "sideBar.dropBackground")]
|
|
||||||
side_bar_drop_background: String,
|
|
||||||
#[serde(rename = "list.activeSelectionBackground")]
|
|
||||||
list_active_selection_background: String,
|
|
||||||
#[serde(rename = "list.inactiveSelectionBackground")]
|
|
||||||
list_inactive_selection_background: String,
|
|
||||||
#[serde(rename = "list.focusBackground")]
|
|
||||||
list_focus_background: String,
|
|
||||||
#[serde(rename = "list.hoverBackground")]
|
|
||||||
list_hover_background: String,
|
|
||||||
|
|
||||||
// text colors
|
|
||||||
#[serde(rename = "editor.foreground")]
|
|
||||||
editor_foreground: String,
|
|
||||||
#[serde(rename = "editorLineNumber.foreground")]
|
|
||||||
editor_line_number_foreground: String,
|
|
||||||
#[serde(rename = "editorCursor.foreground")]
|
|
||||||
editor_cursor_foreground: String,
|
|
||||||
#[serde(rename = "sideBar.foreground")]
|
|
||||||
side_bar_foreground: String,
|
|
||||||
#[serde(rename = "activityBar.foreground")]
|
|
||||||
activity_bar_foreground: String,
|
|
||||||
#[serde(rename = "statusBar.foreground")]
|
|
||||||
status_bar_foreground: String,
|
|
||||||
#[serde(rename = "tab.activeForeground")]
|
|
||||||
tab_active_foreground: String,
|
|
||||||
#[serde(rename = "tab.inactiveForeground")]
|
|
||||||
tab_inactive_foreground: String,
|
|
||||||
#[serde(rename = "editorGroupHeader.tabsForeground")]
|
|
||||||
editor_group_header_tabs_foreground: String,
|
|
||||||
#[serde(rename = "sideBarSectionHeader.foreground")]
|
|
||||||
side_bar_section_header_foreground: String,
|
|
||||||
#[serde(rename = "statusBar.debuggingForeground")]
|
|
||||||
status_bar_debugging_foreground: String,
|
|
||||||
#[serde(rename = "statusBar.noFolderForeground")]
|
|
||||||
status_bar_no_folder_foreground: String,
|
|
||||||
#[serde(rename = "editorWidget.foreground")]
|
|
||||||
editor_widget_foreground: String,
|
|
||||||
#[serde(rename = "editorSuggestWidget.foreground")]
|
|
||||||
editor_suggest_widget_foreground: String,
|
|
||||||
#[serde(rename = "editorHoverWidget.foreground")]
|
|
||||||
editor_hover_widget_foreground: String,
|
|
||||||
#[serde(rename = "input.foreground")]
|
|
||||||
input_foreground: String,
|
|
||||||
#[serde(rename = "dropdown.foreground")]
|
|
||||||
dropdown_foreground: String,
|
|
||||||
#[serde(rename = "terminal.foreground")]
|
|
||||||
terminal_foreground: String,
|
|
||||||
#[serde(rename = "menu.foreground")]
|
|
||||||
menu_foreground: String,
|
|
||||||
#[serde(rename = "panel.foreground")]
|
|
||||||
panel_foreground: String,
|
|
||||||
#[serde(rename = "peekViewEditorGutter.foreground")]
|
|
||||||
peek_view_editor_gutter_foreground: String,
|
|
||||||
#[serde(rename = "peekViewResult.selectionForeground")]
|
|
||||||
peek_view_result_selection_foreground: String,
|
|
||||||
#[serde(rename = "inputOption.activeBorder")]
|
|
||||||
input_option_active_border: String,
|
|
||||||
|
|
||||||
// accent colors
|
|
||||||
#[serde(rename = "activityBarBadge.background")]
|
|
||||||
activity_bar_badge_background: String,
|
|
||||||
#[serde(rename = "statusBar.debuggingBorder")]
|
|
||||||
status_bar_debugging_border: String,
|
|
||||||
#[serde(rename = "button.background")]
|
|
||||||
button_background: String,
|
|
||||||
#[serde(rename = "button.hoverBackground")]
|
|
||||||
button_hover_background: String,
|
|
||||||
#[serde(rename = "statusBarItem.remoteBackground")]
|
|
||||||
status_bar_item_remote_background: String,
|
|
||||||
|
|
||||||
// accent fg colors
|
|
||||||
#[serde(rename = "activityBarBadge.foreground")]
|
|
||||||
activity_bar_badge_foreground: String,
|
|
||||||
#[serde(rename = "button.foreground")]
|
|
||||||
button_foreground: String,
|
|
||||||
#[serde(rename = "textLink.foreground")]
|
|
||||||
text_link_foreground: String,
|
|
||||||
#[serde(rename = "textLink.activeForeground")]
|
|
||||||
text_link_active_foreground: String,
|
|
||||||
#[serde(rename = "peekView.border")]
|
|
||||||
peek_view_border: String,
|
|
||||||
#[serde(rename = "settings.checkboxForeground")]
|
|
||||||
settings_checkbox_foreground: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Theme> for VsTheme {
|
|
||||||
fn from(theme: Theme) -> Self {
|
|
||||||
Self {
|
|
||||||
editor_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
sidebar_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
activity_bar_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
notification_center_header_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
notifications_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
activity_bar_top_active_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
editor_group_header_tabs_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
editor_group_header_no_tabs_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
title_bar_active_background: format!("#{}", to_hex(theme.background.component.base)),
|
|
||||||
title_bar_inactive_background: format!(
|
|
||||||
"#{}",
|
|
||||||
to_hex(theme.background.component.disabled)
|
|
||||||
),
|
|
||||||
status_bar_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
status_bar_no_folder_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
status_bar_debugging_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
tab_active_background: format!("#{}", to_hex(theme.primary.component.pressed)),
|
|
||||||
tab_active_border: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
tab_active_border_top: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
tab_hover_background: format!("#{}", to_hex(theme.primary.component.hover)),
|
|
||||||
tab_inactive_background: format!("#{}", to_hex(theme.primary.component.base)),
|
|
||||||
quick_input_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
side_bar_section_header_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
banner_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
breadcrumb_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
command_center_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
terminal_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
menu_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
panel_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
peek_view_editor_gutter_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
peek_view_result_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
peek_view_title_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
peek_view_editor_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
peek_view_result_selection_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
editor_widget_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
editor_suggest_widget_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
editor_hover_widget_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
input_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
dropdown_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
settings_checkbox_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
settings_text_input_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
settings_number_input_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
settings_dropdown_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
side_bar_drop_background: format!("#{}", to_hex(theme.background.base)),
|
|
||||||
list_active_selection_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
list_inactive_selection_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
list_focus_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
list_hover_background: format!("#{}", to_hex(theme.primary.base)),
|
|
||||||
editor_foreground: format!("#{}", to_hex(theme.background.on)),
|
|
||||||
editor_line_number_foreground: format!("#{}", to_hex(theme.background.on)),
|
|
||||||
editor_cursor_foreground: format!("#{}", to_hex(theme.background.on)),
|
|
||||||
side_bar_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
activity_bar_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
status_bar_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
tab_active_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
tab_inactive_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
editor_group_header_tabs_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
side_bar_section_header_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
status_bar_debugging_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
status_bar_no_folder_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
editor_widget_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
editor_suggest_widget_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
editor_hover_widget_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
input_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
dropdown_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
terminal_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
menu_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
panel_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
peek_view_editor_gutter_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
peek_view_result_selection_foreground: format!("#{}", to_hex(theme.primary.on)),
|
|
||||||
input_option_active_border: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
activity_bar_badge_background: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
activity_bar_badge_foreground: format!("#{}", to_hex(theme.accent.on)),
|
|
||||||
status_bar_debugging_border: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
list_focus_outline: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
button_background: format!("#{}", to_hex(theme.accent_button.base)),
|
|
||||||
button_hover_background: format!("#{}", to_hex(theme.accent_button.hover)),
|
|
||||||
status_bar_item_remote_background: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
button_foreground: format!("#{}", to_hex(theme.accent_button.on)),
|
|
||||||
text_link_foreground: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
text_link_active_foreground: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
peek_view_border: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
settings_checkbox_foreground: format!("#{}", to_hex(theme.accent.base)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Theme {
|
|
||||||
#[cold]
|
|
||||||
pub fn apply_vs_code(self) -> Result<(), OutputError> {
|
|
||||||
let vs_theme = VsTheme::from(self);
|
|
||||||
let mut config_dir = dirs::config_dir().ok_or(OutputError::MissingConfigDir)?;
|
|
||||||
config_dir.extend(["Code", "User"]);
|
|
||||||
let vs_code_dir = config_dir;
|
|
||||||
if !vs_code_dir.exists() {
|
|
||||||
std::fs::create_dir_all(&vs_code_dir).map_err(OutputError::Io)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// just add the json entry for workbench.colorCustomizations
|
|
||||||
let settings_file = vs_code_dir.join("settings.json");
|
|
||||||
let settings = std::fs::read_to_string(&settings_file).unwrap_or_default();
|
|
||||||
let mut settings: serde_json::Value = serde_json::from_str(&settings)?;
|
|
||||||
settings["workbench.colorCustomizations"] = serde_json::to_value(vs_theme).unwrap();
|
|
||||||
settings["window.autoDetectColorScheme"] = serde_json::Value::Bool(true);
|
|
||||||
std::fs::write(
|
|
||||||
&settings_file,
|
|
||||||
serde_json::to_string_pretty(&settings).unwrap(),
|
|
||||||
)
|
|
||||||
.map_err(OutputError::Io)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cold]
|
|
||||||
pub fn reset_vs_code() -> Result<(), OutputError> {
|
|
||||||
let mut config_dir = dirs::config_dir().ok_or(OutputError::MissingConfigDir)?;
|
|
||||||
config_dir.extend(["Code", "User", "settings.json"]);
|
|
||||||
let settings_file = config_dir;
|
|
||||||
// just remove the json entry for workbench.colorCustomizations
|
|
||||||
let settings = std::fs::read_to_string(&settings_file).unwrap_or_default();
|
|
||||||
let mut settings: serde_json::Value = serde_json::from_str(&settings).unwrap_or_default();
|
|
||||||
settings["workbench.colorCustomizations"] = serde_json::Value::Null;
|
|
||||||
|
|
||||||
std::fs::write(
|
|
||||||
&settings_file,
|
|
||||||
serde_json::to_string_pretty(&settings).unwrap(),
|
|
||||||
)
|
|
||||||
.map_err(OutputError::Io)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,228 +0,0 @@
|
||||||
use std::num::NonZeroUsize;
|
|
||||||
|
|
||||||
use almost::equal;
|
|
||||||
use palette::{ClampAssign, FromColor, Lch, Oklcha, Srgb, Srgba, convert::FromColorUnclamped};
|
|
||||||
|
|
||||||
/// Get an array of 100 colors with a specific hue and chroma
|
|
||||||
/// over the full range of lightness.
|
|
||||||
/// Colors which are not valid Srgba will fallback to a color with the nearest valid chroma.
|
|
||||||
pub fn steps<C>(c: C, len: NonZeroUsize) -> Vec<Srgba>
|
|
||||||
where
|
|
||||||
Oklcha: FromColor<C>,
|
|
||||||
{
|
|
||||||
let mut c = Oklcha::from_color(c);
|
|
||||||
let mut steps = Vec::with_capacity(len.get());
|
|
||||||
|
|
||||||
for i in 0..len.get() {
|
|
||||||
let lightness = i as f32 / (len.get() - 1) as f32;
|
|
||||||
c.l = lightness;
|
|
||||||
steps.push(oklch_to_srgba_nearest_chroma(c))
|
|
||||||
}
|
|
||||||
steps
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get the index for a new color some steps away from a base color
|
|
||||||
pub fn get_index(base_index: usize, steps: usize, step_len: usize, is_dark: bool) -> Option<usize> {
|
|
||||||
if is_dark {
|
|
||||||
base_index.checked_add(steps)
|
|
||||||
} else {
|
|
||||||
base_index.checked_sub(steps)
|
|
||||||
}
|
|
||||||
.filter(|i| *i < step_len)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get surface color given a base and some steps
|
|
||||||
pub fn get_surface_color(
|
|
||||||
base_index: usize,
|
|
||||||
steps: usize,
|
|
||||||
step_array: &[Srgba],
|
|
||||||
mut is_dark: bool,
|
|
||||||
fallback: &Srgba,
|
|
||||||
) -> Srgba {
|
|
||||||
assert!(step_array.len() == 100);
|
|
||||||
|
|
||||||
is_dark = is_dark || base_index < 91;
|
|
||||||
|
|
||||||
*get_index(base_index, steps, step_array.len(), is_dark)
|
|
||||||
.and_then(|i| step_array.get(i))
|
|
||||||
.unwrap_or(fallback)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get surface color given a base and some steps
|
|
||||||
#[must_use]
|
|
||||||
pub fn get_small_widget_color(
|
|
||||||
base_index: usize,
|
|
||||||
steps: usize,
|
|
||||||
step_array: &[Srgba],
|
|
||||||
fallback: &Srgba,
|
|
||||||
) -> Srgba {
|
|
||||||
assert!(step_array.len() == 100);
|
|
||||||
|
|
||||||
let is_dark = base_index <= 40 || (base_index > 51 && base_index < 65);
|
|
||||||
|
|
||||||
let res = *get_index(base_index, steps, step_array.len(), is_dark)
|
|
||||||
.and_then(|i| step_array.get(i))
|
|
||||||
.unwrap_or(fallback);
|
|
||||||
|
|
||||||
let mut lch = Lch::from_color(res);
|
|
||||||
if lch.chroma / Lch::<f32>::max_chroma() > 0.03 {
|
|
||||||
lch.chroma = 0.03 * Lch::<f32>::max_chroma();
|
|
||||||
lch.clamp_assign();
|
|
||||||
Srgba::from_color(lch)
|
|
||||||
} else {
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get text color given a base background color
|
|
||||||
pub fn get_text(
|
|
||||||
base_index: usize,
|
|
||||||
step_array: &[Srgba],
|
|
||||||
fallback: &Srgba,
|
|
||||||
tint_array: Option<&[Srgba]>,
|
|
||||||
) -> Srgba {
|
|
||||||
assert!(step_array.len() == 100);
|
|
||||||
let step_array = if let Some(tint_array) = tint_array {
|
|
||||||
assert!(tint_array.len() == 100);
|
|
||||||
tint_array
|
|
||||||
} else {
|
|
||||||
step_array
|
|
||||||
};
|
|
||||||
|
|
||||||
let is_dark = base_index < 60;
|
|
||||||
|
|
||||||
let index = get_index(base_index, 70, step_array.len(), is_dark)
|
|
||||||
.or_else(|| get_index(base_index, 50, step_array.len(), is_dark))
|
|
||||||
.unwrap_or(if is_dark { 99 } else { 0 });
|
|
||||||
|
|
||||||
*step_array.get(index).unwrap_or(fallback)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get the index into the steps array for a given color
|
|
||||||
/// the index is the lightness value of the color converted to Oklcha, scaled to the range [0, 100]
|
|
||||||
pub fn color_index<C>(c: C, array_len: usize) -> usize
|
|
||||||
where
|
|
||||||
Oklcha: FromColor<C>,
|
|
||||||
{
|
|
||||||
let c = Oklcha::from_color(c);
|
|
||||||
((c.l * array_len as f32).round() as usize).clamp(0, array_len - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// find the nearest chroma which makes our color a valid color in Srgba
|
|
||||||
pub fn oklch_to_srgba_nearest_chroma(mut c: Oklcha) -> Srgba {
|
|
||||||
let mut r_chroma = c.chroma;
|
|
||||||
let mut l_chroma = 0.0;
|
|
||||||
// exit early if we found it right away
|
|
||||||
let mut new_c = Srgba::from_color_unclamped(c);
|
|
||||||
|
|
||||||
if is_valid_srgb(new_c) {
|
|
||||||
new_c.clamp_assign();
|
|
||||||
return new_c;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is this an excessive depth to search?
|
|
||||||
for _ in 0..64 {
|
|
||||||
let new_c = Srgba::from_color_unclamped(c);
|
|
||||||
if is_valid_srgb(new_c) {
|
|
||||||
l_chroma = c.chroma;
|
|
||||||
c.chroma = (c.chroma + r_chroma) / 2.0;
|
|
||||||
} else {
|
|
||||||
r_chroma = c.chroma;
|
|
||||||
c.chroma = (c.chroma + l_chroma) / 2.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Srgba::from_color(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// checks that the color is valid srgb
|
|
||||||
pub fn is_valid_srgb(c: Srgba) -> bool {
|
|
||||||
(equal(c.red, Srgb::max_red()) || (c.red >= Srgb::min_red() && c.red <= Srgb::max_red()))
|
|
||||||
&& (equal(c.blue, Srgb::max_blue())
|
|
||||||
|| (c.blue >= Srgb::min_blue() && c.blue <= Srgb::max_blue()))
|
|
||||||
&& (equal(c.green, Srgb::max_green())
|
|
||||||
|| (c.green >= Srgb::min_green() && c.green <= Srgb::max_green()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use palette::{OklabHue, Srgba};
|
|
||||||
|
|
||||||
use super::{is_valid_srgb, oklch_to_srgba_nearest_chroma};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_valid_check() {
|
|
||||||
assert!(is_valid_srgb(Srgba::new(1.0, 1.0, 1.0, 1.0)));
|
|
||||||
assert!(is_valid_srgb(Srgba::new(0.0, 0.0, 0.0, 1.0)));
|
|
||||||
assert!(is_valid_srgb(Srgba::new(0.5, 0.5, 0.5, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(-0.1, 0.0, 0.0, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(0.0, -0.1, 0.0, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(-0.0, 0.0, -0.1, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(-100.1, 0.0, 0.0, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(0.0, -100.1, 0.0, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(-0.0, 0.0, -100.1, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(1.1, 0.0, 0.0, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(0.0, 1.1, 0.0, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(-0.0, 0.0, 1.1, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(100.1, 0.0, 0.0, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(0.0, 100.1, 0.0, 1.0)));
|
|
||||||
assert!(!is_valid_srgb(Srgba::new(-0.0, 0.0, 100.1, 1.0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_conversion_boundaries() {
|
|
||||||
let c1 = palette::Oklcha::new(0.0, 0.288, OklabHue::from_degrees(0.0), 1.0);
|
|
||||||
let srgb = oklch_to_srgba_nearest_chroma(c1);
|
|
||||||
almost::zero(srgb.red);
|
|
||||||
almost::zero(srgb.blue);
|
|
||||||
almost::zero(srgb.green);
|
|
||||||
|
|
||||||
let c1 = palette::Oklcha::new(1.0, 0.288, OklabHue::from_degrees(0.0), 1.0);
|
|
||||||
let srgb = oklch_to_srgba_nearest_chroma(c1);
|
|
||||||
|
|
||||||
almost::equal(srgb.red, 1.0);
|
|
||||||
almost::equal(srgb.blue, 1.0);
|
|
||||||
almost::equal(srgb.green, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_conversion_colors() {
|
|
||||||
let c1 = palette::Oklcha::new(0.4608, 0.11111, OklabHue::new(57.31), 1.0);
|
|
||||||
let srgb = oklch_to_srgba_nearest_chroma(c1).into_format::<u8, u8>();
|
|
||||||
assert_eq!(srgb.red, 133);
|
|
||||||
assert_eq!(srgb.green, 69);
|
|
||||||
assert_eq!(srgb.blue, 0);
|
|
||||||
|
|
||||||
let c1 = palette::Oklcha::new(0.30, 0.08, OklabHue::new(35.0), 1.0);
|
|
||||||
let srgb = oklch_to_srgba_nearest_chroma(c1).into_format::<u8, u8>();
|
|
||||||
assert_eq!(srgb.red, 78);
|
|
||||||
assert_eq!(srgb.green, 27);
|
|
||||||
assert_eq!(srgb.blue, 15);
|
|
||||||
|
|
||||||
let c1 = palette::Oklcha::new(0.757, 0.146, OklabHue::new(301.2), 1.0);
|
|
||||||
let srgb = oklch_to_srgba_nearest_chroma(c1).into_format::<u8, u8>();
|
|
||||||
assert_eq!(srgb.red, 192);
|
|
||||||
assert_eq!(srgb.green, 153);
|
|
||||||
assert_eq!(srgb.blue, 253);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_conversion_fallback_colors() {
|
|
||||||
let c1 = palette::Oklcha::new(0.70, 0.284, OklabHue::new(35.0), 1.0);
|
|
||||||
let srgb = oklch_to_srgba_nearest_chroma(c1).into_format::<u8, u8>();
|
|
||||||
assert_eq!(srgb.red, 255);
|
|
||||||
assert_eq!(srgb.green, 102);
|
|
||||||
assert_eq!(srgb.blue, 65);
|
|
||||||
|
|
||||||
let c1 = palette::Oklcha::new(0.757, 0.239, OklabHue::new(301.2), 1.0);
|
|
||||||
let srgb = oklch_to_srgba_nearest_chroma(c1).into_format::<u8, u8>();
|
|
||||||
assert_eq!(srgb.red, 193);
|
|
||||||
assert_eq!(srgb.green, 152);
|
|
||||||
assert_eq!(srgb.blue, 255);
|
|
||||||
|
|
||||||
let c1 = palette::Oklcha::new(0.163, 0.333, OklabHue::new(141.0), 1.0);
|
|
||||||
let srgb = oklch_to_srgba_nearest_chroma(c1).into_format::<u8, u8>();
|
|
||||||
assert_eq!(srgb.red, 1);
|
|
||||||
assert_eq!(srgb.green, 19);
|
|
||||||
assert_eq!(srgb.blue, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
80
cosmic/action/enum.Action.html
Normal file
80
cosmic/action/enum.Action.html
Normal file
File diff suppressed because one or more lines are too long
1
cosmic/action/fn.app.html
Normal file
1
cosmic/action/fn.app.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `app` fn in crate `cosmic`."><title>app in cosmic::action - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>action</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">action</a></div><h1>Function <span class="fn">app</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/action.rs.html#9-11">Source</a> </span></div><pre class="rust item-decl"><code>pub const fn app<M>(message: M) -> <a class="enum" href="enum.Action.html" title="enum cosmic::action::Action">Action</a><M></code></pre></section></div></main></body></html>
|
||||||
1
cosmic/action/fn.cosmic.html
Normal file
1
cosmic/action/fn.cosmic.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `cosmic` fn in crate `cosmic`."><title>cosmic in cosmic::action - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>action</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">action</a></div><h1>Function <span class="fn">cosmic</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/action.rs.html#13-15">Source</a> </span></div><pre class="rust item-decl"><code>pub const fn cosmic<M>(message: <a class="enum" href="../app/enum.Action.html" title="enum cosmic::app::Action">Action</a>) -> <a class="enum" href="enum.Action.html" title="enum cosmic::action::Action">Action</a><M></code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span></section></div></main></body></html>
|
||||||
1
cosmic/action/fn.none.html
Normal file
1
cosmic/action/fn.none.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `none` fn in crate `cosmic`."><title>none in cosmic::action - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>action</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">action</a></div><h1>Function <span class="fn">none</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/action.rs.html#17-19">Source</a> </span></div><pre class="rust item-decl"><code>pub const fn none<M>() -> <a class="enum" href="enum.Action.html" title="enum cosmic::action::Action">Action</a><M></code></pre></section></div></main></body></html>
|
||||||
2
cosmic/action/index.html
Normal file
2
cosmic/action/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Actions are managed internally by the cosmic runtime."><title>cosmic::action - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module action</a></h2><h3><a href="#enums">Module Items</a></h3><ul class="block"><li><a href="#enums" title="Enums">Enums</a></li><li><a href="#functions" title="Functions">Functions</a></li></ul></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="../index.html">In crate cosmic</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a></div><h1>Module <span>action</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/action.rs.html#4-40">Source</a> </span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Actions are managed internally by the cosmic runtime.</p>
|
||||||
|
</div></details><h2 id="enums" class="section-header">Enums<a href="#enums" class="anchor">§</a></h2><dl class="item-table"><dt><a class="enum" href="enum.Action.html" title="enum cosmic::action::Action">Action</a></dt></dl><h2 id="functions" class="section-header">Functions<a href="#functions" class="anchor">§</a></h2><dl class="item-table"><dt><a class="fn" href="fn.app.html" title="fn cosmic::action::app">app</a></dt><dt><a class="fn" href="fn.cosmic.html" title="fn cosmic::action::cosmic">cosmic</a><wbr><span class="stab portability" title="Available on crate feature `winit` only"><code>winit</code></span></dt><dt><a class="fn" href="fn.none.html" title="fn cosmic::action::none">none</a></dt></dl></section></div></main></body></html>
|
||||||
1
cosmic/action/sidebar-items.js
Normal file
1
cosmic/action/sidebar-items.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
window.SIDEBAR_ITEMS = {"enum":["Action"],"fn":["app","cosmic","none"]};
|
||||||
1
cosmic/all.html
Normal file
1
cosmic/all.html
Normal file
File diff suppressed because one or more lines are too long
3
cosmic/anim/fn.lerp.html
Normal file
3
cosmic/anim/fn.lerp.html
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="A simple linear interpolation calculation function. p = `percent_complete` in decimal form"><title>lerp in cosmic::anim - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>anim</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">anim</a></div><h1>Function <span class="fn">lerp</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/anim.rs.html#6-8">Source</a> </span></div><pre class="rust item-decl"><code>pub fn lerp(start: <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.f32.html">f32</a>, end: <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.f32.html">f32</a>, p: <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.f32.html">f32</a>) -> <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.f32.html">f32</a></code></pre><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>A simple linear interpolation calculation function.
|
||||||
|
p = <code>percent_complete</code> in decimal form</p>
|
||||||
|
</div></details></section></div></main></body></html>
|
||||||
3
cosmic/anim/fn.slerp.html
Normal file
3
cosmic/anim/fn.slerp.html
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="A fast smooth interpolation calculation function. p = `percent_complete` in decimal form"><title>slerp in cosmic::anim - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>anim</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">anim</a></div><h1>Function <span class="fn">slerp</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/anim.rs.html#13-16">Source</a> </span></div><pre class="rust item-decl"><code>pub fn slerp(start: <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.f32.html">f32</a>, end: <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.f32.html">f32</a>, p: <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.f32.html">f32</a>) -> <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.f32.html">f32</a></code></pre><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>A fast smooth interpolation calculation function.
|
||||||
|
p = <code>percent_complete</code> in decimal form</p>
|
||||||
|
</div></details></section></div></main></body></html>
|
||||||
2
cosmic/anim/fn.smootherstep.html
Normal file
2
cosmic/anim/fn.smootherstep.html
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="utility function which maps a value [0, 1] -> [0, 1] using the smootherstep function"><title>smootherstep in cosmic::anim - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>anim</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">anim</a></div><h1>Function <span class="fn">smootherstep</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/anim.rs.html#19-21">Source</a> </span></div><pre class="rust item-decl"><code>pub fn smootherstep(t: <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.f32.html">f32</a>) -> <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.f32.html">f32</a></code></pre><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>utility function which maps a value [0, 1] -> [0, 1] using the smootherstep function</p>
|
||||||
|
</div></details></section></div></main></body></html>
|
||||||
3
cosmic/anim/index.html
Normal file
3
cosmic/anim/index.html
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `anim` mod in crate `cosmic`."><title>cosmic::anim - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module anim</a></h2><h3><a href="#structs">Module Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li><li><a href="#functions" title="Functions">Functions</a></li></ul></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="../index.html">In crate cosmic</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a></div><h1>Module <span>anim</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/anim.rs.html#1-51">Source</a> </span></div><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><dl class="item-table"><dt><a class="struct" href="struct.State.html" title="struct cosmic::anim::State">State</a></dt></dl><h2 id="functions" class="section-header">Functions<a href="#functions" class="anchor">§</a></h2><dl class="item-table"><dt><a class="fn" href="fn.lerp.html" title="fn cosmic::anim::lerp">lerp</a></dt><dd>A simple linear interpolation calculation function.
|
||||||
|
p = <code>percent_complete</code> in decimal form</dd><dt><a class="fn" href="fn.slerp.html" title="fn cosmic::anim::slerp">slerp</a></dt><dd>A fast smooth interpolation calculation function.
|
||||||
|
p = <code>percent_complete</code> in decimal form</dd><dt><a class="fn" href="fn.smootherstep.html" title="fn cosmic::anim::smootherstep">smootherstep</a></dt><dd>utility function which maps a value [0, 1] -> [0, 1] using the smootherstep function</dd></dl></section></div></main></body></html>
|
||||||
1
cosmic/anim/sidebar-items.js
Normal file
1
cosmic/anim/sidebar-items.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
window.SIDEBAR_ITEMS = {"fn":["lerp","slerp","smootherstep"],"struct":["State"]};
|
||||||
68
cosmic/anim/struct.State.html
Normal file
68
cosmic/anim/struct.State.html
Normal file
File diff suppressed because one or more lines are too long
11
cosmic/app/action/enum.Action.html
Normal file
11
cosmic/app/action/enum.Action.html
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="refresh" content="0;URL=../../../cosmic/app/enum.Action.html">
|
||||||
|
<title>Redirection</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Redirecting to <a href="../../../cosmic/app/enum.Action.html">../../../cosmic/app/enum.Action.html</a>...</p>
|
||||||
|
<script>location.replace("../../../cosmic/app/enum.Action.html" + location.search + location.hash);</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4
cosmic/app/context_drawer/fn.context_drawer.html
Normal file
4
cosmic/app/context_drawer/fn.context_drawer.html
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `context_drawer` fn in crate `cosmic`."><title>context_drawer in cosmic::app::context_drawer - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>app::<wbr>context_<wbr>drawer</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../../index.html">cosmic</a>::<wbr><a href="../index.html">app</a>::<wbr><a href="index.html">context_drawer</a></div><h1>Function <span class="fn">context_drawer</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../../src/cosmic/app/context_drawer.rs.html#26-38">Source</a> </span></div><pre class="rust item-decl"><code>pub fn context_drawer<'a, Message: <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + 'static>(
|
||||||
|
content: impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/convert/trait.Into.html" title="trait core::convert::Into">Into</a><<a class="type" href="../../type.Element.html" title="type cosmic::Element">Element</a><'a, Message>>,
|
||||||
|
on_close: Message,
|
||||||
|
) -> <a class="struct" href="struct.ContextDrawer.html" title="struct cosmic::app::context_drawer::ContextDrawer">ContextDrawer</a><'a, Message></code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span></section></div></main></body></html>
|
||||||
1
cosmic/app/context_drawer/index.html
Normal file
1
cosmic/app/context_drawer/index.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `context_drawer` mod in crate `cosmic`."><title>cosmic::app::context_drawer - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../../static.files/storage-68b7e25d.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module context_<wbr>drawer</a></h2><h3><a href="#structs">Module Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li><li><a href="#functions" title="Functions">Functions</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="../index.html">In cosmic::<wbr>app</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../../index.html">cosmic</a>::<wbr><a href="../index.html">app</a></div><h1>Module <span>context_drawer</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../../src/cosmic/app/context_drawer.rs.html#4-78">Source</a> </span></div><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><dl class="item-table"><dt><a class="struct" href="struct.ContextDrawer.html" title="struct cosmic::app::context_drawer::ContextDrawer">Context<wbr>Drawer</a></dt></dl><h2 id="functions" class="section-header">Functions<a href="#functions" class="anchor">§</a></h2><dl class="item-table"><dt><a class="fn" href="fn.context_drawer.html" title="fn cosmic::app::context_drawer::context_drawer">context_<wbr>drawer</a></dt></dl></section></div></main></body></html>
|
||||||
1
cosmic/app/context_drawer/sidebar-items.js
Normal file
1
cosmic/app/context_drawer/sidebar-items.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
window.SIDEBAR_ITEMS = {"fn":["context_drawer"],"struct":["ContextDrawer"]};
|
||||||
75
cosmic/app/context_drawer/struct.ContextDrawer.html
Normal file
75
cosmic/app/context_drawer/struct.ContextDrawer.html
Normal file
File diff suppressed because one or more lines are too long
94
cosmic/app/cosmic/enum.WindowingSystem.html
Normal file
94
cosmic/app/cosmic/enum.WindowingSystem.html
Normal file
File diff suppressed because one or more lines are too long
1
cosmic/app/cosmic/fn.windowing_system.html
Normal file
1
cosmic/app/cosmic/fn.windowing_system.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `windowing_system` fn in crate `cosmic`."><title>windowing_system in cosmic::app::cosmic - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>app::<wbr>cosmic</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../../index.html">cosmic</a>::<wbr><a href="../index.html">app</a>::<wbr><a href="index.html">cosmic</a></div><h1>Function <span class="fn">windowing_system</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../../src/cosmic/app/cosmic.rs.html#48-50">Source</a> </span></div><pre class="rust item-decl"><code>pub fn windowing_system() -> <a class="enum" href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="enum.WindowingSystem.html" title="enum cosmic::app::cosmic::WindowingSystem">WindowingSystem</a>></code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span></section></div></main></body></html>
|
||||||
1
cosmic/app/cosmic/index.html
Normal file
1
cosmic/app/cosmic/index.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `cosmic` mod in crate `cosmic`."><title>cosmic::app::cosmic - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../../static.files/storage-68b7e25d.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module cosmic</a></h2><h3><a href="#structs">Module Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li><li><a href="#enums" title="Enums">Enums</a></li><li><a href="#functions" title="Functions">Functions</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="../index.html">In cosmic::<wbr>app</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../../index.html">cosmic</a>::<wbr><a href="../index.html">app</a></div><h1>Module <span>cosmic</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../../src/cosmic/app/cosmic.rs.html#4-1376">Source</a> </span></div><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><dl class="item-table"><dt><a class="struct" href="struct.Cosmic.html" title="struct cosmic::app::cosmic::Cosmic">Cosmic</a></dt></dl><h2 id="enums" class="section-header">Enums<a href="#enums" class="anchor">§</a></h2><dl class="item-table"><dt><a class="enum" href="enum.WindowingSystem.html" title="enum cosmic::app::cosmic::WindowingSystem">Windowing<wbr>System</a></dt></dl><h2 id="functions" class="section-header">Functions<a href="#functions" class="anchor">§</a></h2><dl class="item-table"><dt><a class="fn" href="fn.windowing_system.html" title="fn cosmic::app::cosmic::windowing_system">windowing_<wbr>system</a></dt></dl></section></div></main></body></html>
|
||||||
1
cosmic/app/cosmic/sidebar-items.js
Normal file
1
cosmic/app/cosmic/sidebar-items.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
window.SIDEBAR_ITEMS = {"enum":["WindowingSystem"],"fn":["windowing_system"],"struct":["Cosmic"]};
|
||||||
91
cosmic/app/cosmic/struct.Cosmic.html
Normal file
91
cosmic/app/cosmic/struct.Cosmic.html
Normal file
File diff suppressed because one or more lines are too long
128
cosmic/app/enum.Action.html
Normal file
128
cosmic/app/enum.Action.html
Normal file
File diff suppressed because one or more lines are too long
4
cosmic/app/fn.run.html
Normal file
4
cosmic/app/fn.run.html
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Launch a COSMIC application with the given `Settings`."><title>run in cosmic::app - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">run</a></h2><h3><a href="#">Sections</a></h3><ul class="block top-toc"><li><a href="#errors" title="Errors">Errors</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>app</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">app</a></div><h1>Function <span class="fn">run</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/app/mod.rs.html#130-187">Source</a> </span></div><pre class="rust item-decl"><code>pub fn run<App: <a class="trait" href="../trait.Application.html" title="trait cosmic::Application">Application</a>>(settings: <a class="struct" href="settings/struct.Settings.html" title="struct cosmic::app::settings::Settings">Settings</a>, flags: App::<a class="associatedtype" href="../trait.Application.html#associatedtype.Flags" title="type cosmic::Application::Flags">Flags</a>) -> <a class="type" href="../iced/type.Result.html" title="type cosmic::iced::Result">Result</a></code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Launch a COSMIC application with the given <a href="settings/struct.Settings.html" title="struct cosmic::app::settings::Settings"><code>Settings</code></a>.</p>
|
||||||
|
<h2 id="errors"><a class="doc-anchor" href="#errors">§</a>Errors</h2>
|
||||||
|
<p>Returns error on application failure.</p>
|
||||||
|
</div></details></section></div></main></body></html>
|
||||||
11
cosmic/app/fn.run_single_instance.html
Normal file
11
cosmic/app/fn.run_single_instance.html
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Launch a COSMIC application with the given `Settings`. If the application is already running, the arguments will be passed to the running instance."><title>run_single_instance in cosmic::app - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">run_<wbr>single_<wbr>instance</a></h2><h3><a href="#">Sections</a></h3><ul class="block top-toc"><li><a href="#errors" title="Errors">Errors</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>app</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">app</a></div><h1>Function <span class="fn">run_single_instance</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/app/mod.rs.html#195-305">Source</a> </span></div><pre class="rust item-decl"><code>pub fn run_single_instance<App: <a class="trait" href="../trait.Application.html" title="trait cosmic::Application">Application</a>>(
|
||||||
|
settings: <a class="struct" href="settings/struct.Settings.html" title="struct cosmic::app::settings::Settings">Settings</a>,
|
||||||
|
flags: App::<a class="associatedtype" href="../trait.Application.html#associatedtype.Flags" title="type cosmic::Application::Flags">Flags</a>,
|
||||||
|
) -> <a class="type" href="../iced/type.Result.html" title="type cosmic::iced::Result">Result</a><div class="where">where
|
||||||
|
App::<a class="associatedtype" href="../trait.Application.html#associatedtype.Flags" title="type cosmic::Application::Flags">Flags</a>: <a class="trait" href="trait.CosmicFlags.html" title="trait cosmic::app::CosmicFlags">CosmicFlags</a>,
|
||||||
|
App::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>: <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + <a class="trait" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/fmt/trait.Debug.html" title="trait cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::fmt::Debug">Debug</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> + 'static,</div></code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate features <code>winit</code> and <code>single-instance</code></strong> only.</div></span><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Launch a COSMIC application with the given <a href="settings/struct.Settings.html" title="struct cosmic::app::settings::Settings"><code>Settings</code></a>.
|
||||||
|
If the application is already running, the arguments will be passed to the
|
||||||
|
running instance.</p>
|
||||||
|
<h2 id="errors"><a class="doc-anchor" href="#errors">§</a>Errors</h2>
|
||||||
|
<p>Returns error on application failure.</p>
|
||||||
|
</div></details></section></div></main></body></html>
|
||||||
6
cosmic/app/index.html
Normal file
6
cosmic/app/index.html
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Build interactive cross-platform COSMIC applications."><title>cosmic::app - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module app</a></h2><h3><a href="#reexports">Module Items</a></h3><ul class="block"><li><a href="#reexports" title="Re-exports">Re-exports</a></li><li><a href="#modules" title="Modules">Modules</a></li><li><a href="#enums" title="Enums">Enums</a></li><li><a href="#traits" title="Traits">Traits</a></li><li><a href="#functions" title="Functions">Functions</a></li><li><a href="#types" title="Type Aliases">Type Aliases</a></li></ul></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="../index.html">In crate cosmic</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a></div><h1>Module <span>app</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/app/mod.rs.html#4-906">Source</a> </span></div><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Build interactive cross-platform COSMIC applications.</p>
|
||||||
|
<p>Check out our <a href="https://github.com/pop-os/libcosmic/tree/master/examples/application">application</a>
|
||||||
|
example in our repository.</p>
|
||||||
|
</div></details><h2 id="reexports" class="section-header">Re-exports<a href="#reexports" class="anchor">§</a></h2><dl class="item-table reexports"><dt id="reexport.ContextDrawer"><code>pub use context_drawer::<a class="struct" href="context_drawer/struct.ContextDrawer.html" title="struct cosmic::app::context_drawer::ContextDrawer">ContextDrawer</a>;</code></dt><dt id="reexport.context_drawer"><code>pub use context_drawer::<a class="fn" href="context_drawer/fn.context_drawer.html" title="fn cosmic::app::context_drawer::context_drawer">context_drawer</a>;</code></dt><dt id="reexport.Core"><code>pub use crate::<a class="struct" href="../struct.Core.html" title="struct cosmic::Core">Core</a>;</code></dt><dt id="reexport.Settings"><code>pub use settings::<a class="struct" href="settings/struct.Settings.html" title="struct cosmic::app::settings::Settings">Settings</a>;</code></dt></dl><h2 id="modules" class="section-header">Modules<a href="#modules" class="anchor">§</a></h2><dl class="item-table"><dt><a class="mod" href="context_drawer/index.html" title="mod cosmic::app::context_drawer">context_<wbr>drawer</a></dt><dt><a class="mod" href="cosmic/index.html" title="mod cosmic::app::cosmic">cosmic</a></dt><dt><a class="mod" href="settings/index.html" title="mod cosmic::app::settings">settings</a></dt><dd>Configure a new COSMIC application.</dd></dl><h2 id="enums" class="section-header">Enums<a href="#enums" class="anchor">§</a></h2><dl class="item-table"><dt><a class="enum" href="enum.Action.html" title="enum cosmic::app::Action">Action</a></dt><dd>A message managed internally by COSMIC.</dd></dl><h2 id="traits" class="section-header">Traits<a href="#traits" class="anchor">§</a></h2><dl class="item-table"><dt><a class="trait" href="trait.Application.html" title="trait cosmic::app::Application">Application</a></dt><dd>An interactive cross-platform COSMIC application.</dd><dt><a class="trait" href="trait.ApplicationExt.html" title="trait cosmic::app::ApplicationExt">Application<wbr>Ext</a></dt><dd>Methods automatically derived for all types implementing <a href="../trait.Application.html" title="trait cosmic::Application"><code>Application</code></a>.</dd><dt><a class="trait" href="trait.CosmicFlags.html" title="trait cosmic::app::CosmicFlags">Cosmic<wbr>Flags</a></dt></dl><h2 id="functions" class="section-header">Functions<a href="#functions" class="anchor">§</a></h2><dl class="item-table"><dt><a class="fn" href="fn.run.html" title="fn cosmic::app::run">run</a></dt><dd>Launch a COSMIC application with the given <a href="settings/struct.Settings.html" title="struct cosmic::app::settings::Settings"><code>Settings</code></a>.</dd><dt><a class="fn" href="fn.run_single_instance.html" title="fn cosmic::app::run_single_instance">run_<wbr>single_<wbr>instance</a><wbr><span class="stab portability" title="Available on crate feature `single-instance` only"><code>single-instance</code></span></dt><dd>Launch a COSMIC application with the given <a href="settings/struct.Settings.html" title="struct cosmic::app::settings::Settings"><code>Settings</code></a>.
|
||||||
|
If the application is already running, the arguments will be passed to the
|
||||||
|
running instance.</dd></dl><h2 id="types" class="section-header">Type Aliases<a href="#types" class="anchor">§</a></h2><dl class="item-table"><dt><a class="type" href="type.Task.html" title="type cosmic::app::Task">Task</a></dt></dl></section></div></main></body></html>
|
||||||
2
cosmic/app/settings/index.html
Normal file
2
cosmic/app/settings/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Configure a new COSMIC application."><title>cosmic::app::settings - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../../static.files/storage-68b7e25d.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module settings</a></h2><h3><a href="#structs">Module Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="../index.html">In cosmic::<wbr>app</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../../index.html">cosmic</a>::<wbr><a href="../index.html">app</a></div><h1>Module <span>settings</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../../src/cosmic/app/settings.rs.html#4-105">Source</a> </span></div><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Configure a new COSMIC application.</p>
|
||||||
|
</div></details><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><dl class="item-table"><dt><a class="struct" href="struct.Settings.html" title="struct cosmic::app::settings::Settings">Settings</a></dt><dd>Configure a new COSMIC application.</dd></dl></section></div></main></body></html>
|
||||||
1
cosmic/app/settings/sidebar-items.js
Normal file
1
cosmic/app/settings/sidebar-items.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
window.SIDEBAR_ITEMS = {"struct":["Settings"]};
|
||||||
85
cosmic/app/settings/struct.Settings.html
Normal file
85
cosmic/app/settings/struct.Settings.html
Normal file
File diff suppressed because one or more lines are too long
1
cosmic/app/sidebar-items.js
Normal file
1
cosmic/app/sidebar-items.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
window.SIDEBAR_ITEMS = {"enum":["Action"],"fn":["run","run_single_instance"],"mod":["context_drawer","cosmic","settings"],"trait":["Application","ApplicationExt","CosmicFlags"],"type":["Task"]};
|
||||||
97
cosmic/app/trait.Application.html
Normal file
97
cosmic/app/trait.Application.html
Normal file
File diff suppressed because one or more lines are too long
36
cosmic/app/trait.ApplicationExt.html
Normal file
36
cosmic/app/trait.ApplicationExt.html
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Methods automatically derived for all types implementing `Application`."><title>ApplicationExt in cosmic::app - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc trait"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Application<wbr>Ext</a></h2><h3><a href="#required-methods">Required Methods</a></h3><ul class="block"><li><a href="#tymethod.drag" title="drag">drag</a></li><li><a href="#tymethod.maximize" title="maximize">maximize</a></li><li><a href="#tymethod.minimize" title="minimize">minimize</a></li><li><a href="#tymethod.set_window_title" title="set_window_title">set_window_title</a></li><li><a href="#tymethod.title" title="title">title</a></li><li><a href="#tymethod.view_main" title="view_main">view_main</a></li></ul><h3><a href="#provided-methods">Provided Methods</a></h3><ul class="block"><li><a href="#method.set_header_title" title="set_header_title">set_header_title</a></li><li><a href="#method.set_show_context" title="set_show_context">set_show_context</a></li><li><a href="#method.watch_config" title="watch_config">watch_config</a></li><li><a href="#method.watch_state" title="watch_state">watch_state</a></li></ul><h3><a href="#dyn-compatibility">Dyn Compatibility</a></h3><h3><a href="#implementors">Implementors</a></h3></section><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>app</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">app</a></div><h1>Trait <span class="trait">ApplicationExt</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/app/mod.rs.html#512-564">Source</a> </span></div><pre class="rust item-decl"><code>pub trait ApplicationExt: <a class="trait" href="../trait.Application.html" title="trait cosmic::Application">Application</a> {
|
||||||
|
// Required methods
|
||||||
|
fn <a href="#tymethod.drag" class="fn">drag</a>(&mut self) -> <a class="type" href="type.Task.html" title="type cosmic::app::Task">Task</a><Self::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>>;
|
||||||
|
<span class="item-spacer"></span> fn <a href="#tymethod.maximize" class="fn">maximize</a>(&mut self) -> <a class="type" href="type.Task.html" title="type cosmic::app::Task">Task</a><Self::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>>;
|
||||||
|
<span class="item-spacer"></span> fn <a href="#tymethod.minimize" class="fn">minimize</a>(&mut self) -> <a class="type" href="type.Task.html" title="type cosmic::app::Task">Task</a><Self::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>>;
|
||||||
|
<span class="item-spacer"></span> fn <a href="#tymethod.title" class="fn">title</a>(&self, id: <a class="struct" href="../iced/window/struct.Id.html" title="struct cosmic::iced::window::Id">Id</a>) -> &<a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.str.html">str</a>;
|
||||||
|
<span class="item-spacer"></span> fn <a href="#tymethod.set_window_title" class="fn">set_window_title</a>(&mut self, title: <a class="struct" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/string/struct.String.html" title="struct cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::string::String">String</a>, id: <a class="struct" href="../iced/window/struct.Id.html" title="struct cosmic::iced::window::Id">Id</a>) -> <a class="type" href="type.Task.html" title="type cosmic::app::Task">Task</a><Self::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>>;
|
||||||
|
<span class="item-spacer"></span> fn <a href="#tymethod.view_main" class="fn">view_main</a>(&self) -> <a class="type" href="../type.Element.html" title="type cosmic::Element">Element</a><'_, <a class="enum" href="../action/enum.Action.html" title="enum cosmic::action::Action">Action</a><Self::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>>>;
|
||||||
|
|
||||||
|
// Provided methods
|
||||||
|
fn <a href="#method.set_show_context" class="fn">set_show_context</a>(&mut self, show: <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.bool.html">bool</a>) { ... }
|
||||||
|
<span class="item-spacer"></span> fn <a href="#method.set_header_title" class="fn">set_header_title</a>(&mut self, title: <a class="struct" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/string/struct.String.html" title="struct cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::string::String">String</a>) { ... }
|
||||||
|
<span class="item-spacer"></span> fn <a href="#method.watch_config" class="fn">watch_config</a><T: <a class="trait" href="../cosmic_config/trait.CosmicConfigEntry.html" title="trait cosmic::cosmic_config::CosmicConfigEntry">CosmicConfigEntry</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Sync.html" title="trait core::marker::Sync">Sync</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/default/trait.Default.html" title="trait core::default::Default">Default</a> + 'static + <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialEq.html" title="trait core::cmp::PartialEq">PartialEq</a>>(
|
||||||
|
&self,
|
||||||
|
id: &'static <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.str.html">str</a>,
|
||||||
|
) -> <a class="struct" href="../iced/struct.Subscription.html" title="struct cosmic::iced::Subscription">Subscription</a><<a class="struct" href="../cosmic_config/struct.Update.html" title="struct cosmic::cosmic_config::Update">Update</a><T>> { ... }
|
||||||
|
<span class="item-spacer"></span> fn <a href="#method.watch_state" class="fn">watch_state</a><T: <a class="trait" href="../cosmic_config/trait.CosmicConfigEntry.html" title="trait cosmic::cosmic_config::CosmicConfigEntry">CosmicConfigEntry</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Sync.html" title="trait core::marker::Sync">Sync</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/default/trait.Default.html" title="trait core::default::Default">Default</a> + 'static + <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialEq.html" title="trait core::cmp::PartialEq">PartialEq</a>>(
|
||||||
|
&self,
|
||||||
|
id: &'static <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.str.html">str</a>,
|
||||||
|
) -> <a class="struct" href="../iced/struct.Subscription.html" title="struct cosmic::iced::Subscription">Subscription</a><<a class="struct" href="../cosmic_config/struct.Update.html" title="struct cosmic::cosmic_config::Update">Update</a><T>> { ... }
|
||||||
|
}</code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Methods automatically derived for all types implementing <a href="../trait.Application.html" title="trait cosmic::Application"><code>Application</code></a>.</p>
|
||||||
|
</div></details><h2 id="required-methods" class="section-header">Required Methods<a href="#required-methods" class="anchor">§</a></h2><div class="methods"><details class="toggle method-toggle" open><summary><section id="tymethod.drag" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#514">Source</a><h4 class="code-header">fn <a href="#tymethod.drag" class="fn">drag</a>(&mut self) -> <a class="type" href="type.Task.html" title="type cosmic::app::Task">Task</a><Self::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>></h4></section></summary><div class="docblock"><p>Initiates a window drag.</p>
|
||||||
|
</div></details><details class="toggle method-toggle" open><summary><section id="tymethod.maximize" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#517">Source</a><h4 class="code-header">fn <a href="#tymethod.maximize" class="fn">maximize</a>(&mut self) -> <a class="type" href="type.Task.html" title="type cosmic::app::Task">Task</a><Self::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>></h4></section></summary><div class="docblock"><p>Maximizes the window.</p>
|
||||||
|
</div></details><details class="toggle method-toggle" open><summary><section id="tymethod.minimize" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#520">Source</a><h4 class="code-header">fn <a href="#tymethod.minimize" class="fn">minimize</a>(&mut self) -> <a class="type" href="type.Task.html" title="type cosmic::app::Task">Task</a><Self::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>></h4></section></summary><div class="docblock"><p>Minimizes the window.</p>
|
||||||
|
</div></details><details class="toggle method-toggle" open><summary><section id="tymethod.title" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#528">Source</a><h4 class="code-header">fn <a href="#tymethod.title" class="fn">title</a>(&self, id: <a class="struct" href="../iced/window/struct.Id.html" title="struct cosmic::iced::window::Id">Id</a>) -> &<a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.str.html">str</a></h4></section><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>multi-window</code></strong> only.</div></span></summary><div class="docblock"><p>Get the title of a window.</p>
|
||||||
|
</div></details><details class="toggle method-toggle" open><summary><section id="tymethod.set_window_title" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#546">Source</a><h4 class="code-header">fn <a href="#tymethod.set_window_title" class="fn">set_window_title</a>(&mut self, title: <a class="struct" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/string/struct.String.html" title="struct cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::string::String">String</a>, id: <a class="struct" href="../iced/window/struct.Id.html" title="struct cosmic::iced::window::Id">Id</a>) -> <a class="type" href="type.Task.html" title="type cosmic::app::Task">Task</a><Self::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>></h4></section><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>multi-window</code></strong> only.</div></span></summary><div class="docblock"><p>Set the title of a window.</p>
|
||||||
|
</div></details><details class="toggle method-toggle" open><summary><section id="tymethod.view_main" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#549">Source</a><h4 class="code-header">fn <a href="#tymethod.view_main" class="fn">view_main</a>(&self) -> <a class="type" href="../type.Element.html" title="type cosmic::Element">Element</a><'_, <a class="enum" href="../action/enum.Action.html" title="enum cosmic::action::Action">Action</a><Self::<a class="associatedtype" href="../trait.Application.html#associatedtype.Message" title="type cosmic::Application::Message">Message</a>>></h4></section></summary><div class="docblock"><p>View template for the main window.</p>
|
||||||
|
</div></details></div><h2 id="provided-methods" class="section-header">Provided Methods<a href="#provided-methods" class="anchor">§</a></h2><div class="methods"><details class="toggle method-toggle" open><summary><section id="method.set_show_context" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#531-533">Source</a><h4 class="code-header">fn <a href="#method.set_show_context" class="fn">set_show_context</a>(&mut self, show: <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.bool.html">bool</a>)</h4></section></summary><div class="docblock"><p>Set the context drawer visibility.</p>
|
||||||
|
</div></details><details class="toggle method-toggle" open><summary><section id="method.set_header_title" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#536-538">Source</a><h4 class="code-header">fn <a href="#method.set_header_title" class="fn">set_header_title</a>(&mut self, title: <a class="struct" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/string/struct.String.html" title="struct cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::string::String">String</a>)</h4></section></summary><div class="docblock"><p>Set the header bar title.</p>
|
||||||
|
</div></details><section id="method.watch_config" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#551-556">Source</a><h4 class="code-header">fn <a href="#method.watch_config" class="fn">watch_config</a><T: <a class="trait" href="../cosmic_config/trait.CosmicConfigEntry.html" title="trait cosmic::cosmic_config::CosmicConfigEntry">CosmicConfigEntry</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Sync.html" title="trait core::marker::Sync">Sync</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/default/trait.Default.html" title="trait core::default::Default">Default</a> + 'static + <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialEq.html" title="trait core::cmp::PartialEq">PartialEq</a>>(
|
||||||
|
&self,
|
||||||
|
id: &'static <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.str.html">str</a>,
|
||||||
|
) -> <a class="struct" href="../iced/struct.Subscription.html" title="struct cosmic::iced::Subscription">Subscription</a><<a class="struct" href="../cosmic_config/struct.Update.html" title="struct cosmic::cosmic_config::Update">Update</a><T>></h4></section><section id="method.watch_state" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#558-563">Source</a><h4 class="code-header">fn <a href="#method.watch_state" class="fn">watch_state</a><T: <a class="trait" href="../cosmic_config/trait.CosmicConfigEntry.html" title="trait cosmic::cosmic_config::CosmicConfigEntry">CosmicConfigEntry</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Sync.html" title="trait core::marker::Sync">Sync</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/default/trait.Default.html" title="trait core::default::Default">Default</a> + 'static + <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/cmp/trait.PartialEq.html" title="trait core::cmp::PartialEq">PartialEq</a>>(
|
||||||
|
&self,
|
||||||
|
id: &'static <a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.str.html">str</a>,
|
||||||
|
) -> <a class="struct" href="../iced/struct.Subscription.html" title="struct cosmic::iced::Subscription">Subscription</a><<a class="struct" href="../cosmic_config/struct.Update.html" title="struct cosmic::cosmic_config::Update">Update</a><T>></h4></section></div><h2 id="dyn-compatibility" class="section-header">Dyn Compatibility<a href="#dyn-compatibility" class="anchor">§</a></h2><div class="dyn-compatibility-info"><p>This trait is <b>not</b> <a href="https://doc.rust-lang.org/nightly/reference/items/traits.html#dyn-compatibility">dyn compatible</a>.</p><p><i>In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.</i></p></div><h2 id="implementors" class="section-header">Implementors<a href="#implementors" class="anchor">§</a></h2><div id="implementors-list"><section id="impl-ApplicationExt-for-App" class="impl"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#566-885">Source</a><a href="#impl-ApplicationExt-for-App" class="anchor">§</a><h3 class="code-header">impl<App: <a class="trait" href="../trait.Application.html" title="trait cosmic::Application">Application</a>> <a class="trait" href="../trait.ApplicationExt.html" title="trait cosmic::ApplicationExt">ApplicationExt</a> for App</h3></section></div><script src="../../trait.impl/cosmic/app/trait.ApplicationExt.js" async></script></section></div></main></body></html>
|
||||||
8
cosmic/app/trait.CosmicFlags.html
Normal file
8
cosmic/app/trait.CosmicFlags.html
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `CosmicFlags` trait in crate `cosmic`."><title>CosmicFlags in cosmic::app - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc trait"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Cosmic<wbr>Flags</a></h2><h3><a href="#required-associated-types">Required Associated Types</a></h3><ul class="block"><li><a href="#associatedtype.Args" title="Args">Args</a></li><li><a href="#associatedtype.SubCommand" title="SubCommand">SubCommand</a></li></ul><h3><a href="#provided-methods">Provided Methods</a></h3><ul class="block"><li><a href="#method.action" title="action">action</a></li><li><a href="#method.args" title="args">args</a></li></ul><h3><a href="#implementors">Implementors</a></h3></section><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>app</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">app</a></div><h1>Trait <span class="trait">CosmicFlags</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/app/mod.rs.html#307-319">Source</a> </span></div><pre class="rust item-decl"><code>pub trait CosmicFlags {
|
||||||
|
type <a href="#associatedtype.SubCommand" class="associatedtype">SubCommand</a>: <a class="trait" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/string/trait.ToString.html" title="trait cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::string::ToString">ToString</a> + <a class="trait" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/fmt/trait.Debug.html" title="trait cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::fmt::Debug">Debug</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> + 'static;
|
||||||
|
type <a href="#associatedtype.Args" class="associatedtype">Args</a>: <a class="trait" href="https://doc.rust-lang.org/nightly/core/convert/trait.Into.html" title="trait core::convert::Into">Into</a><<a class="struct" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/vec/struct.Vec.html" title="struct cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::vec::Vec">Vec</a><<a class="struct" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/string/struct.String.html" title="struct cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::string::String">String</a>>> + <a class="trait" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/fmt/trait.Debug.html" title="trait cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::fmt::Debug">Debug</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> + 'static;
|
||||||
|
|
||||||
|
// Provided methods
|
||||||
|
fn <a href="#method.action" class="fn">action</a>(&self) -> <a class="enum" href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html" title="enum core::option::Option">Option</a><&Self::<a class="associatedtype" href="trait.CosmicFlags.html#associatedtype.SubCommand" title="type cosmic::app::CosmicFlags::SubCommand">SubCommand</a>> { ... }
|
||||||
|
<span class="item-spacer"></span> fn <a href="#method.args" class="fn">args</a>(&self) -> <a class="struct" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/vec/struct.Vec.html" title="struct cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::vec::Vec">Vec</a><&<a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.str.html">str</a>> { ... }
|
||||||
|
}</code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span><h2 id="required-associated-types" class="section-header">Required Associated Types<a href="#required-associated-types" class="anchor">§</a></h2><div class="methods"><section id="associatedtype.SubCommand" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#308">Source</a><h4 class="code-header">type <a href="#associatedtype.SubCommand" class="associatedtype">SubCommand</a>: <a class="trait" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/string/trait.ToString.html" title="trait cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::string::ToString">ToString</a> + <a class="trait" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/fmt/trait.Debug.html" title="trait cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::fmt::Debug">Debug</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> + 'static</h4></section><section id="associatedtype.Args" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#309">Source</a><h4 class="code-header">type <a href="#associatedtype.Args" class="associatedtype">Args</a>: <a class="trait" href="https://doc.rust-lang.org/nightly/core/convert/trait.Into.html" title="trait core::convert::Into">Into</a><<a class="struct" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/vec/struct.Vec.html" title="struct cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::vec::Vec">Vec</a><<a class="struct" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/string/struct.String.html" title="struct cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::string::String">String</a>>> + <a class="trait" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/fmt/trait.Debug.html" title="trait cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::fmt::Debug">Debug</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + <a class="trait" href="https://doc.rust-lang.org/nightly/core/marker/trait.Send.html" title="trait core::marker::Send">Send</a> + 'static</h4></section></div><h2 id="provided-methods" class="section-header">Provided Methods<a href="#provided-methods" class="anchor">§</a></h2><div class="methods"><section id="method.action" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#311-313">Source</a><h4 class="code-header">fn <a href="#method.action" class="fn">action</a>(&self) -> <a class="enum" href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html" title="enum core::option::Option">Option</a><&Self::<a class="associatedtype" href="trait.CosmicFlags.html#associatedtype.SubCommand" title="type cosmic::app::CosmicFlags::SubCommand">SubCommand</a>></h4></section><section id="method.args" class="method"><a class="src rightside" href="../../src/cosmic/app/mod.rs.html#316-318">Source</a><h4 class="code-header">fn <a href="#method.args" class="fn">args</a>(&self) -> <a class="struct" href="../cctk/sctk/reexports/client/backend/smallvec/alloc/vec/struct.Vec.html" title="struct cosmic::cctk::sctk::reexports::client::backend::smallvec::alloc::vec::Vec">Vec</a><&<a class="primitive" href="https://doc.rust-lang.org/nightly/std/primitive.str.html">str</a>></h4></section></div><h2 id="implementors" class="section-header">Implementors<a href="#implementors" class="anchor">§</a></h2><div id="implementors-list"></div><script src="../../trait.impl/cosmic/app/trait.CosmicFlags.js" async></script></section></div></main></body></html>
|
||||||
1
cosmic/app/type.Task.html
Normal file
1
cosmic/app/type.Task.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `Task` type in crate `cosmic`."><title>Task in cosmic::app - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc type"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Task</a></h2><h3><a href="#aliased-type">Aliased Type</a></h3></section><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>app</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">app</a></div><h1>Type Alias <span class="type">Task</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/app/mod.rs.html#18">Source</a> </span></div><pre class="rust item-decl"><code>pub type Task<M> = <a class="struct" href="../struct.Task.html" title="struct cosmic::Task">Task</a><<a class="enum" href="../action/enum.Action.html" title="enum cosmic::action::Action">Action</a><M>>;</code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>winit</code></strong> only.</div></span><h2 id="aliased-type" class="section-header">Aliased Type<a href="#aliased-type" class="anchor">§</a></h2><pre class="rust item-decl"><code>pub struct Task<M> { <span class="comment">/* private fields */</span> }</code></pre><script src="../../type.impl/cosmic/struct.Task.js" data-self-path="cosmic::app::Task" async></script></section></div></main></body></html>
|
||||||
2
cosmic/applet/column/index.html
Normal file
2
cosmic/applet/column/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Distribute content vertically."><title>cosmic::applet::column - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../../static.files/storage-68b7e25d.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module column</a></h2><h3><a href="#structs">Module Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="../index.html">In cosmic::<wbr>applet</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../../index.html">cosmic</a>::<wbr><a href="../index.html">applet</a></div><h1>Module <span>column</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../../src/cosmic/applet/column.rs.html#1-517">Source</a> </span></div><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>applet</code></strong> only.</div></span><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Distribute content vertically.</p>
|
||||||
|
</div></details><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><dl class="item-table"><dt><a class="struct" href="struct.Column.html" title="struct cosmic::applet::column::Column">Column</a></dt><dd>A container that distributes its contents vertically.</dd><dt><a class="struct" href="struct.State.html" title="struct cosmic::applet::column::State">State</a></dt></dl></section></div></main></body></html>
|
||||||
1
cosmic/applet/column/sidebar-items.js
Normal file
1
cosmic/applet/column/sidebar-items.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
window.SIDEBAR_ITEMS = {"struct":["Column","State"]};
|
||||||
176
cosmic/applet/column/struct.Column.html
Normal file
176
cosmic/applet/column/struct.Column.html
Normal file
File diff suppressed because one or more lines are too long
70
cosmic/applet/column/struct.State.html
Normal file
70
cosmic/applet/column/struct.State.html
Normal file
File diff suppressed because one or more lines are too long
73
cosmic/applet/enum.PanelType.html
Normal file
73
cosmic/applet/enum.PanelType.html
Normal file
File diff suppressed because one or more lines are too long
78
cosmic/applet/enum.Size.html
Normal file
78
cosmic/applet/enum.Size.html
Normal file
File diff suppressed because one or more lines are too long
3
cosmic/applet/fn.menu_button.html
Normal file
3
cosmic/applet/fn.menu_button.html
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `menu_button` fn in crate `cosmic`."><title>menu_button in cosmic::applet - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>applet</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">applet</a></div><h1>Function <span class="fn">menu_button</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/applet/mod.rs.html#609-616">Source</a> </span></div><pre class="rust item-decl"><code>pub fn menu_button<'a, Message: <a class="trait" href="https://doc.rust-lang.org/nightly/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a> + 'a>(
|
||||||
|
content: impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/convert/trait.Into.html" title="trait core::convert::Into">Into</a><<a class="type" href="../type.Element.html" title="type cosmic::Element">Element</a><'a, Message>>,
|
||||||
|
) -> <a class="struct" href="../widget/struct.Button.html" title="struct cosmic::widget::Button">Button</a><'a, Message></code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>applet</code></strong> only.</div></span></section></div></main></body></html>
|
||||||
1
cosmic/applet/fn.menu_control_padding.html
Normal file
1
cosmic/applet/fn.menu_control_padding.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `menu_control_padding` fn in crate `cosmic`."><title>menu_control_padding in cosmic::applet - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>applet</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">applet</a></div><h1>Function <span class="fn">menu_control_padding</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/applet/mod.rs.html#626-630">Source</a> </span></div><pre class="rust item-decl"><code>pub fn menu_control_padding() -> <a class="struct" href="../iced/struct.Padding.html" title="struct cosmic::iced::Padding">Padding</a></code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>applet</code></strong> only.</div></span></section></div></main></body></html>
|
||||||
3
cosmic/applet/fn.padded_control.html
Normal file
3
cosmic/applet/fn.padded_control.html
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `padded_control` fn in crate `cosmic`."><title>padded_control in cosmic::applet - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>applet</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">applet</a></div><h1>Function <span class="fn">padded_control</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/applet/mod.rs.html#618-624">Source</a> </span></div><pre class="rust item-decl"><code>pub fn padded_control<'a, Message>(
|
||||||
|
content: impl <a class="trait" href="https://doc.rust-lang.org/nightly/core/convert/trait.Into.html" title="trait core::convert::Into">Into</a><<a class="type" href="../type.Element.html" title="type cosmic::Element">Element</a><'a, Message>>,
|
||||||
|
) -> <a class="struct" href="../widget/struct.Container.html" title="struct cosmic::widget::Container">Container</a><'a, Message, <a class="struct" href="../struct.Theme.html" title="struct cosmic::Theme">Theme</a>, <a class="type" href="../type.Renderer.html" title="type cosmic::Renderer">Renderer</a>></code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>applet</code></strong> only.</div></span></section></div></main></body></html>
|
||||||
4
cosmic/applet/fn.run.html
Normal file
4
cosmic/applet/fn.run.html
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Launch the application with the given settings."><title>run in cosmic::applet - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">run</a></h2><h3><a href="#">Sections</a></h3><ul class="block top-toc"><li><a href="#errors" title="Errors">Errors</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>applet</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">applet</a></div><h1>Function <span class="fn">run</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/applet/mod.rs.html#541-597">Source</a> </span></div><pre class="rust item-decl"><code>pub fn run<App: <a class="trait" href="../trait.Application.html" title="trait cosmic::Application">Application</a>>(flags: App::<a class="associatedtype" href="../trait.Application.html#associatedtype.Flags" title="type cosmic::Application::Flags">Flags</a>) -> <a class="type" href="../iced/type.Result.html" title="type cosmic::iced::Result">Result</a></code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>applet</code></strong> only.</div></span><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Launch the application with the given settings.</p>
|
||||||
|
<h2 id="errors"><a class="doc-anchor" href="#errors">§</a>Errors</h2>
|
||||||
|
<p>Returns error on application failure.</p>
|
||||||
|
</div></details></section></div></main></body></html>
|
||||||
1
cosmic/applet/fn.style.html
Normal file
1
cosmic/applet/fn.style.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `style` fn in crate `cosmic`."><title>style in cosmic::applet - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../static.files/storage-68b7e25d.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><div id="rustdoc-modnav"><h2><a href="index.html">In cosmic::<wbr>applet</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../index.html">cosmic</a>::<wbr><a href="index.html">applet</a></div><h1>Function <span class="fn">style</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/cosmic/applet/mod.rs.html#600-607">Source</a> </span></div><pre class="rust item-decl"><code>pub fn style() -> <a class="struct" href="../iced/daemon/program/graphics/core/theme/struct.Style.html" title="struct cosmic::iced::daemon::program::graphics::core::theme::Style">Style</a></code></pre><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>applet</code></strong> only.</div></span></section></div></main></body></html>
|
||||||
1
cosmic/applet/index.html
Normal file
1
cosmic/applet/index.html
Normal file
File diff suppressed because one or more lines are too long
2
cosmic/applet/row/index.html
Normal file
2
cosmic/applet/row/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Distribute content horizontally."><title>cosmic::applet::row - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../../static.files/storage-68b7e25d.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module row</a></h2><h3><a href="#structs">Module Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="../index.html">In cosmic::<wbr>applet</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../../index.html">cosmic</a>::<wbr><a href="../index.html">applet</a></div><h1>Module <span>row</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../../src/cosmic/applet/row.rs.html#1-507">Source</a> </span></div><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>applet</code></strong> only.</div></span><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Distribute content horizontally.</p>
|
||||||
|
</div></details><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><dl class="item-table"><dt><a class="struct" href="struct.Row.html" title="struct cosmic::applet::row::Row">Row</a></dt><dd>A container that distributes its contents horizontally.</dd><dt><a class="struct" href="struct.State.html" title="struct cosmic::applet::row::State">State</a></dt></dl></section></div></main></body></html>
|
||||||
1
cosmic/applet/row/sidebar-items.js
Normal file
1
cosmic/applet/row/sidebar-items.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
window.SIDEBAR_ITEMS = {"struct":["Row","State"]};
|
||||||
175
cosmic/applet/row/struct.Row.html
Normal file
175
cosmic/applet/row/struct.Row.html
Normal file
File diff suppressed because one or more lines are too long
70
cosmic/applet/row/struct.State.html
Normal file
70
cosmic/applet/row/struct.State.html
Normal file
File diff suppressed because one or more lines are too long
1
cosmic/applet/sidebar-items.js
Normal file
1
cosmic/applet/sidebar-items.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
window.SIDEBAR_ITEMS = {"enum":["PanelType","Size"],"fn":["menu_button","menu_control_padding","padded_control","run","style"],"mod":["column","row"],"struct":["Context"]};
|
||||||
114
cosmic/applet/struct.Context.html
Normal file
114
cosmic/applet/struct.Context.html
Normal file
File diff suppressed because one or more lines are too long
2
cosmic/cctk/cosmic_protocols/a11y/index.html
Normal file
2
cosmic/cctk/cosmic_protocols/a11y/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Accessibility support."><title>cosmic::cctk::cosmic_protocols::a11y - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../../static.files/rustdoc-aa0817cf.css"><meta name="rustdoc-vars" data-root-path="../../../../" data-static-root-path="../../../../static.files/" data-current-crate="cosmic" data-themes="" data-resource-suffix="" data-rustdoc-version="1.90.0-nightly (3048886e5 2025-07-30)" data-channel="nightly" data-search-js="search-fa3e91e5.js" data-settings-js="settings-5514c975.js" ><script src="../../../../static.files/storage-68b7e25d.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../../../static.files/main-eebb9057.js"></script><noscript><link rel="stylesheet" href="../../../../static.files/noscript-32bb7600.css"></noscript><link rel="alternate icon" type="image/png" href="../../../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../../../cosmic/index.html">cosmic</a><span class="version">1.0.0</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module a11y</a></h2><h3><a href="#modules">Module Items</a></h3><ul class="block"><li><a href="#modules" title="Modules">Modules</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="../index.html">In cosmic::<wbr>cctk::<wbr>cosmic_<wbr>protocols</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../../../index.html">cosmic</a>::<wbr><a href="../../index.html">cctk</a>::<wbr><a href="../index.html">cosmic_protocols</a></div><h1>Module <span>a11y</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../../../src/cosmic_protocols/lib.rs.html#20">Source</a> </span></div><span class="item-info"><div class="stab portability">Available on <strong>crate feature <code>wayland</code> and Linux</strong> only.</div></span><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Accessibility support.</p>
|
||||||
|
</div></details><h2 id="modules" class="section-header">Modules<a href="#modules" class="anchor">§</a></h2><dl class="item-table"><dt><a class="mod" href="v1/index.html" title="mod cosmic::cctk::cosmic_protocols::a11y::v1">v1</a></dt></dl></section></div></main></body></html>
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue