Compare commits

...

13 commits

Author SHA1 Message Date
3daac73eff chore: use local graphics dependencies 2026-06-13 08:35:47 +02:00
f84e98536c chore: use local COSMIC support crates 2026-06-13 08:35:47 +02:00
ae8be3a1eb fix: drop iced_winit/single-instance feature ref
Upstream dc84488c "fix(iced): double IME commit on GNOME desktop" wires
the libcosmic single-instance feature through iced_winit/single-instance,
but our pinned iced fork (yoda-wayland-only @ 81639935) does not carry
that feature yet. Drop the ref so libcosmic-yoda compiles after rebase;
the GNOME IME fix needs to be ported separately into the iced submodule
before this can be reinstated.

Leyoda 2026 – GPLv3
2026-06-13 08:35:47 +02:00
74e1e1baaf yoda: use local dbus settings bindings 2026-06-13 08:35:47 +02:00
0d184816cc feat(flex_row): reorderable rows with shadow constant gated (squashed)
Squash of 2 yoda commits:
- 7dd0ee83 feat: reorderable flex row
- b1b8203a fix: gate reorderable flex row shadow constant
2026-06-13 08:35:47 +02:00
03f3769373 yoda: warning cleanup sweep (dead code + clippy --fix) (squashed)
Squash of 4 yoda commits:
- 84437e21 yoda: libcosmic-yoda dead-code purge (14->0 warnings)
- 999db0a4 yoda: cosmic-theme cleanup (4->0 warnings) — workspace at 0 warnings total
- 4743bb8e yoda: cargo clippy --fix on libcosmic-yoda (115->33 warnings)
- 675f3b59 chore: reduce local stack warnings
2026-06-13 08:35:47 +02:00
f9ff7496f3 yoda: bump iced submodule + cargo auto-fix sweeps (squashed)
Squash of 6 yoda commits:
- 282813c8 yoda: bump iced -> window_clipboard via public Forgejo fork
- cdf34938 yoda: cargo fix --lib (libcosmic-yoda) — drop 99 trivial warnings
- 38a988cb yoda: cargo fix on cosmic-config + bump iced auto-fix commit
- 301bbf6e yoda: bump iced submodule -> iced_winit warning cleanup (0 left)
- b94c03d9 yoda: bump iced submodule -> iced_widget cleanup (0 left)
- a9492d76 yoda: bump iced submodule -> all iced crates at 0 warnings
2026-06-13 08:35:47 +02:00
ba0b06da3c feat(cosmic-theme): add apply_gtk_decoration_layout helper
Writes the gtk-decoration-layout key to ~/.config/gtk-{3,4}.0/settings.ini
and best-effort updates GNOME's button-layout GSettings key for apps that
still consult it. Factors out write_gtk_settings_key for reuse.

Leyoda 2026 – GPLv3
2026-06-13 08:35:47 +02:00
2134eedc67 yoda: bump iced submodule (Wayland-only + softbuffer cuts) (squashed)
Squash of 3 yoda commits:
- c118f5a2 yoda: bump iced submodule ref -> yoda-wayland-only HEAD 8f6be798
- 388e0655 yoda: bump iced submodule -> softbuffer + window_clipboard cuts
- 9b2a3643 Update iced warning fixes
2026-06-13 08:25:37 +02:00
ac9caf8c2a yoda: fork pivot — Wayland-only + ungate winit + soft-fork libcosmic-yoda (squashed)
Squash of 7 yoda commits forming the fork pivot:
- 255cf7cc rename: libcosmic -> libcosmic-yoda (fork 0.1.0-yoda)
- 8701aa31 feat(yoda): Wayland-only cut — drop winit and x11 features
- 6736a596 yoda: soft-fork pivot — keep Cargo name 'libcosmic' for dep unification
- 3e23d087 yoda: re-apply hard rename — libcosmic -> libcosmic-yoda (0.1.0-yoda)
- aec3eb61 yoda: ungate remaining winit+wayland combined cfgs
- 8ab7b158 yoda-v2: color_picker Theme ref + context_menu/menu ungate winit
- 8d1d8739 yoda: drop x11 defaults on iced_winit + iced_tiny_skia
2026-06-13 08:24:24 +02:00
afff77bbfe header_bar: add WindowControlsPosition (macOS-style left controls)
Adds a new public enum `WindowControlsPosition { Start, End }` and a
matching field on `HeaderBar`, allowing window controls (close / minimize
/ maximize) to be packed on the start side of the headerbar (macOS
style, icon order close → minimize → maximize) instead of the default
end side (Linux / GNOME style, minimize → maximize → close).

Wiring:
- `crate::widget::WindowControlsPosition` re-exported alongside
  `HeaderBar`.
- `HeaderBar::controls_position(Option<WindowControlsPosition>)` setter;
  when left unset, falls back to `crate::config::window_controls_position()`
  (reads `CosmicTk.window_controls_position`), mirroring how `density`
  falls back to `header_size()`.
- New `CosmicTk.window_controls_position` field with default `End` for
  backwards compatibility; serde-friendly enum so existing configs keep
  working via `#[serde(default)]` semantics.

Tested with cosmic-yoterm, cosmic-settings, cosmic-edit, cosmic-files
rebuilt against this libcosmic via a local `[patch]` override. Config
changes picked up live through the existing cosmic-config subscription.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-13 08:24:24 +02:00
b4a8fd65e6 feat(segmented_button): on_double_click + internal tab reorder (squashed)
Squash of 2 yoda commits:
- 108441ef segmented_button: add on_double_click callback
- a322516f segmented_button: fix internal tab reorder end-to-end
2026-06-13 08:24:24 +02:00
0c91735d11 perf: throttle malloc_trim + avoid VecDeque clones (squashed)
Squash of 2 yoda commits:
- 77262dd0 perf(malloc): throttle malloc_trim to 1 Hz in hot paths
- 1d98eee6 perf(widget): avoid VecDeque clone in segmented_button/table Model::clear
2026-06-13 08:24:24 +02:00
145 changed files with 611 additions and 439 deletions

View file

@ -1,6 +1,11 @@
[package] [package]
name = "libcosmic" # Yoda fork: hard-renamed. Every consumer (leyoda/cosmic-files fork + each
version = "1.0.0" # leyoda/cosmic-* app) depends directly on `libcosmic-yoda` by path, bypassing
# pop-os/libcosmic entirely. No [patch] shenanigans needed — transitive deps
# that used to ask for `libcosmic` are replaced by deps on our forks that ask
# for `libcosmic-yoda`.
name = "libcosmic-yoda"
version = "0.1.0-yoda.2"
edition = "2024" edition = "2024"
rust-version = "1.93" rust-version = "1.93"
@ -9,12 +14,10 @@ name = "cosmic"
[features] [features]
default = [ default = [
"winit",
"tokio", "tokio",
"a11y", "a11y",
"dbus-config", "dbus-config",
"x11", "wayland",
"iced-wayland",
"multi-window", "multi-window",
] ]
advanced-shaping = ["iced/advanced-shaping"] advanced-shaping = ["iced/advanced-shaping"]
@ -35,7 +38,6 @@ animated-image = [
autosize = [] autosize = []
applet = [ applet = [
"autosize", "autosize",
"winit",
"wayland", "wayland",
"tokio", "tokio",
"cosmic-panel-config", "cosmic-panel-config",
@ -69,7 +71,7 @@ desktop-systemd-scope = ["desktop", "dep:zbus"]
# Enables keycode serialization # Enables keycode serialization
serde-keycode = ["iced_core/serde"] serde-keycode = ["iced_core/serde"]
# Prevents multiple separate process instances. # Prevents multiple separate process instances.
single-instance = ["iced_winit/single-instance", "zbus/blocking-api", "ron"] single-instance = ["zbus/blocking-api", "ron"]
# smol async runtime # smol async runtime
smol = ["dep:smol", "iced/smol", "zbus?/async-io", "rfd?/async-std"] smol = ["dep:smol", "iced/smol", "zbus?/async-io", "rfd?/async-std"]
tokio = [ tokio = [
@ -81,32 +83,34 @@ tokio = [
"cosmic-config/tokio", "cosmic-config/tokio",
] ]
# Tokio async runtime # Tokio async runtime
# Wayland window support # Wayland window support (yoda fork is Wayland-only; always active in default).
iced-wayland = [ # We still need iced/winit because pop-os/iced hosts the runtime dispatcher
# (`iced_winit as shell`) there — the name is a misnomer, it's the same crate
# that provides both the winit path AND the sctk/cctk wayland path.
wayland = [
"ashpd?/wayland", "ashpd?/wayland",
"autosize", "autosize",
"iced/winit",
"iced/wayland", "iced/wayland",
"iced_winit/wayland", "iced_winit/wayland",
"surface-message",
]
wayland = [
"iced-wayland",
"iced_runtime/cctk", "iced_runtime/cctk",
"iced_winit/cctk", "iced_winit/cctk",
"iced_wgpu/cctk", "iced_wgpu/cctk",
"iced/cctk", "iced/cctk",
"dep:iced_winit",
"dep:cctk", "dep:cctk",
"surface-message",
] ]
surface-message = [] surface-message = []
# multi-window support # multi-window support
multi-window = [] multi-window = []
# Render with wgpu # Render with wgpu
wgpu = ["iced/wgpu", "iced_wgpu"] wgpu = ["iced/wgpu", "iced_wgpu"]
# X11 window support via winit # Compat stubs — kept empty so upstream deps (cosmic-files, cosmic-text, …)
winit = ["iced/winit", "iced_winit"] # that still ask for `winit` / `x11` features resolve cleanly against the
winit_debug = ["winit", "debug"] # yoda fork. Activating them has no effect: no code is gated on these.
winit_tokio = ["winit", "tokio"] winit = []
winit_wgpu = ["winit", "wgpu"] x11 = []
# Enables XDG portal integrations # Enables XDG portal integrations
xdg-portal = ["ashpd"] xdg-portal = ["ashpd"]
qr_code = ["iced/qr_code"] qr_code = ["iced/qr_code"]
@ -119,7 +123,6 @@ async-std = [
"zbus?/async-io", "zbus?/async-io",
"iced/async-std", "iced/async-std",
] ]
x11 = ["iced/x11", "iced_winit/x11"]
[dependencies] [dependencies]
apply = "0.3.0" apply = "0.3.0"
@ -127,10 +130,10 @@ ashpd = { version = "0.12.3", default-features = false, optional = true }
async-fs = { version = "2.2", optional = true } async-fs = { version = "2.2", optional = true }
async-std = { workspace = true, optional = true } async-std = { workspace = true, optional = true }
auto_enums = "0.8.8" auto_enums = "0.8.8"
cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "c253ec1", optional = true } cctk = { path = "../cosmic-protocols/client-toolkit", package = "cosmic-client-toolkit", optional = true }
jiff = "0.2" jiff = "0.2"
cosmic-config = { path = "cosmic-config" } cosmic-config = { path = "cosmic-config" }
cosmic-settings-config = { git = "https://github.com/pop-os/cosmic-settings-daemon", optional = true } cosmic-settings-config = { path = "../cosmic-settings-daemon/config", optional = true }
# Internationalization # Internationalization
i18n-embed = { version = "0.16.0", features = [ i18n-embed = { version = "0.16.0", features = [
"fluent-system", "fluent-system",
@ -174,11 +177,11 @@ ron = { workspace = true, optional = true }
# Enable DBus feature on Linux targets # Enable DBus feature on Linux targets
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
cosmic-config = { path = "cosmic-config", features = ["dbus"] } cosmic-config = { path = "cosmic-config", features = ["dbus"] }
cosmic-settings-daemon = { git = "https://github.com/pop-os/dbus-settings-bindings" } cosmic-settings-daemon = { path = "../dbus-settings-bindings/cosmic-settings-daemon" }
zbus.workspace = true zbus = { version = "5.14.0", default-features = false }
[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies] [target.'cfg(all(unix, not(target_os = "macos")))'.dependencies]
freedesktop-icons = { package = "cosmic-freedesktop-icons", git = "https://github.com/pop-os/freedesktop-icons" } freedesktop-icons = { package = "cosmic-freedesktop-icons", path = "../cosmic-freedesktop-icons" }
freedesktop-desktop-entry = { version = "0.8.1", optional = true } freedesktop-desktop-entry = { version = "0.8.1", optional = true }
shlex = { version = "1.3.0", optional = true } shlex = { version = "1.3.0", optional = true }
@ -224,28 +227,58 @@ optional = true
[dependencies.iced_tiny_skia] [dependencies.iced_tiny_skia]
path = "./iced/tiny_skia" path = "./iced/tiny_skia"
# Yoda: drop the x11 default → softbuffer no longer pulls tiny-xlib/x11-dl/etc.
default-features = false
features = ["wayland"]
[dependencies.iced_winit] [dependencies.iced_winit]
path = "./iced/winit" path = "./iced/winit"
optional = true optional = true
# Yoda: drop the x11 default → winit won't pull winit-x11/tiny-xlib/x11-dl.
# Keep wayland + wayland-dlopen (default behaviour minus x11).
default-features = false
features = ["wayland", "wayland-dlopen"]
[dependencies.iced_wgpu] [dependencies.iced_wgpu]
path = "./iced/wgpu" path = "./iced/wgpu"
optional = true optional = true
[dependencies.cosmic-panel-config] [dependencies.cosmic-panel-config]
git = "https://github.com/pop-os/cosmic-panel" path = "../cosmic-panel/cosmic-panel-config"
# path = "../cosmic-panel/cosmic-panel-config"
optional = true optional = true
[patch.'https://github.com/pop-os/freedesktop-icons']
cosmic-freedesktop-icons = { path = "../cosmic-freedesktop-icons" }
[patch.'https://github.com/pop-os/softbuffer']
softbuffer = { path = "../softbuffer" }
[patch.'https://github.com/pop-os/smithay-clipboard']
smithay-clipboard = { path = "../smithay-clipboard" }
[patch.'https://github.com/pop-os/winit.git']
dpi = { path = "../winit/dpi" }
winit = { path = "../winit/winit" }
winit-android = { path = "../winit/winit-android" }
winit-appkit = { path = "../winit/winit-appkit" }
winit-common = { path = "../winit/winit-common" }
winit-core = { path = "../winit/winit-core" }
winit-orbital = { path = "../winit/winit-orbital" }
winit-uikit = { path = "../winit/winit-uikit" }
winit-wayland = { path = "../winit/winit-wayland" }
winit-web = { path = "../winit/winit-web" }
winit-win32 = { path = "../winit/winit-win32" }
winit-x11 = { path = "../winit/winit-x11" }
[workspace] [workspace]
members = [ members = [
"cosmic-config", "cosmic-config",
"cosmic-config-derive", "cosmic-config-derive",
"cosmic-theme", "cosmic-theme",
"examples/*",
] ]
exclude = ["iced"] # examples/* excluded — many depend on the removed winit/x11 features.
# They will be revisited and adapted in a later phase.
exclude = ["iced", "examples"]
[workspace.dependencies] [workspace.dependencies]
async-std = "1.13" async-std = "1.13"
@ -258,5 +291,13 @@ tracing = "0.1"
tokio = "1.52" tokio = "1.52"
zbus = {version = "5.15", default-features = false} zbus = {version = "5.15", default-features = false}
# Speed up snapshot diffing in cosmic-theme tests. Cargo silently ignores
# [profile.*] blocks in non-root manifests, so this lives at the
# workspace root.
[profile.dev.package.insta]
opt-level = 3
[profile.dev.package.similar]
opt-level = 3
[dev-dependencies] [dev-dependencies]
tempfile = "3.27.0" tempfile = "3.27.0"

View file

@ -10,8 +10,8 @@ macro = ["cosmic-config-derive"]
subscription = ["iced_futures"] subscription = ["iced_futures"]
[dependencies] [dependencies]
cosmic-settings-daemon = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true } cosmic-settings-daemon = { path = "../../dbus-settings-bindings/cosmic-settings-daemon", optional = true }
zbus = { workspace = true, default-features = false, optional = true } zbus = { version = "5.14.0", default-features = false, optional = true }
atomicwrites = { git = "https://github.com/jackpot51/rust-atomicwrites" } atomicwrites = { git = "https://github.com/jackpot51/rust-atomicwrites" }
calloop = { version = "0.14.4", optional = true } calloop = { version = "0.14.4", optional = true }
notify = "8.2.0" notify = "8.2.0"

View file

@ -34,6 +34,3 @@ thiserror.workspace = true
[dev-dependencies] [dev-dependencies]
insta = "1.47.2" insta = "1.47.2"
[profile.dev.package]
insta.opt-level = 3
similar.opt-level = 3

View file

@ -955,6 +955,12 @@ impl ThemeBuilder {
} }
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
// The component_hovered/pressed_overlay vars are seeded once near the
// top of this fn and then reassigned inside each container block
// (primary, secondary, …) before being read again. The initial seed
// is therefore overwritten before any read, which is what the
// unused_assignments lint flags below.
#[allow(unused_assignments)]
/// build the theme /// build the theme
pub fn build(self) -> Theme { pub fn build(self) -> Theme {
let Self { let Self {

View file

@ -1,12 +1,13 @@
use crate::composite::over; use crate::{Component, Theme, composite::over, steps::steps};
use crate::steps::steps; use configparser::ini::Ini;
use crate::{Component, Theme}; use palette::{Darken, IntoColor, Lighten, Srgba, WithAlpha, rgb::Rgba};
use palette::rgb::Rgba; use std::{
use palette::{Darken, IntoColor, Lighten, Srgba, WithAlpha}; fs::{self, File},
use std::fs::{self, File}; io::{self, Write},
use std::io::{self, Write}; num::NonZeroUsize,
use std::num::NonZeroUsize; path::Path,
use std::path::Path; process::Command,
};
use super::{OutputError, to_rgba}; use super::{OutputError, to_rgba};
@ -218,6 +219,50 @@ impl Theme {
Ok(()) Ok(())
} }
/// Apply the preferred GTK client-side decoration button layout.
///
/// This writes the GTK 3/4 `settings.ini` value used by GTK header bars and
/// also best-effort updates GNOME's `button-layout` GSettings key for apps
/// that still consult it.
///
/// # Errors
///
/// Returns an `OutputError` if the GTK settings files cannot be written.
#[cold]
pub fn apply_gtk_decoration_layout(buttons_at_start: bool) -> Result<(), OutputError> {
let Some(config_dir) = dirs::config_dir() else {
return Err(OutputError::MissingConfigDir);
};
let layout = if buttons_at_start {
"close,minimize,maximize:"
} else {
":minimize,maximize,close"
};
for gtk_version in ["gtk-3.0", "gtk-4.0"] {
let gtk_dir = config_dir.join(gtk_version);
fs::create_dir_all(&gtk_dir).map_err(OutputError::Io)?;
Self::write_gtk_settings_key(
&gtk_dir.join("settings.ini"),
"gtk-decoration-layout",
layout,
)?;
}
// best-effort: gsettings is absent on non-GNOME systems
let _ = Command::new("gsettings")
.args([
"set",
"org.gnome.desktop.wm.preferences",
"button-layout",
layout,
])
.status();
Ok(())
}
/// Reset the applied gtk css /// Reset the applied gtk css
/// ///
/// # Errors /// # Errors
@ -257,6 +302,20 @@ impl Theme {
Ok(()) Ok(())
} }
#[cold]
fn write_gtk_settings_key(path: &Path, key: &str, value: &str) -> Result<(), OutputError> {
let mut ini = Ini::new_cs();
if path.exists() {
let file_content = fs::read_to_string(path).map_err(OutputError::Io)?;
ini.read(file_content).map_err(OutputError::Ini)?;
}
ini.setstr("Settings", key, Some(value));
ini.pretty_write(path, &super::qt_settings_ini_style())
.map_err(OutputError::Io)
}
fn is_cosmic_css(path: &Path, cosmic_css: &Path) -> io::Result<Option<bool>> { fn is_cosmic_css(path: &Path, cosmic_css: &Path) -> io::Result<Option<bool>> {
if !path.exists() { if !path.exists() {
return Ok(None); return Ok(None);

View file

@ -266,6 +266,14 @@ impl From<Theme> for VsTheme {
} }
impl Theme { impl Theme {
/// Write this theme to VS Code's `settings.json` as a
/// `workbench.colorCustomizations` entry, and enable
/// `window.autoDetectColorScheme` so VS Code follows the system theme.
///
/// # Errors
///
/// Returns an `OutputError` if the user config dir is missing, the
/// settings file cannot be read/written, or its JSON is invalid.
#[cold] #[cold]
pub fn apply_vs_code(self) -> Result<(), OutputError> { pub fn apply_vs_code(self) -> Result<(), OutputError> {
let vs_theme = VsTheme::from(self); let vs_theme = VsTheme::from(self);
@ -291,6 +299,13 @@ impl Theme {
Ok(()) Ok(())
} }
/// Remove the `workbench.colorCustomizations` entry previously written
/// by [`Theme::apply_vs_code`] from VS Code's `settings.json`.
///
/// # Errors
///
/// Returns an `OutputError` if the user config dir is missing, the
/// settings file cannot be read/written, or its JSON is invalid.
#[cold] #[cold]
pub fn reset_vs_code() -> Result<(), OutputError> { pub fn reset_vs_code() -> Result<(), OutputError> {
let mut config_dir = dirs::config_dir().ok_or(OutputError::MissingConfigDir)?; let mut config_dir = dirs::config_dir().ok_or(OutputError::MissingConfigDir)?;

View file

@ -6,7 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
open = "5.3.3" open = "5.3.3"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
path = "../../" path = "../../"
features = [ features = [
"debug", "debug",

View file

@ -12,7 +12,7 @@ tracing = "0.1"
env_logger = "0.10.2" env_logger = "0.10.2"
log = "0.4.29" log = "0.4.29"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
path = "../../" path = "../../"
default-features = false default-features = false
features = ["applet-token"] features = ["applet-token"]

View file

@ -5,12 +5,12 @@ edition = "2021"
[features] [features]
default = ["wayland"] default = ["wayland"]
wayland = ["libcosmic/wayland"] wayland = ["libcosmic-yoda/wayland"]
[dependencies] [dependencies]
env_logger = "0.11" env_logger = "0.11"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
path = "../../" path = "../../"
features = [ features = [
"debug", "debug",

View file

@ -8,6 +8,6 @@ edition = "2024"
[dependencies] [dependencies]
jiff = "0.2" jiff = "0.2"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
path = "../../" path = "../../"
features = ["debug", "winit", "tokio", "xdg-portal", "wgpu"] features = ["debug", "winit", "tokio", "xdg-portal", "wgpu"]

View file

@ -8,7 +8,7 @@ tracing = "0.1.44"
tracing-subscriber = "0.3.22" tracing-subscriber = "0.3.22"
tracing-log = "0.2.0" tracing-log = "0.2.0"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
path = "../../" path = "../../"
features = [ features = [
"debug", "debug",

View file

@ -8,7 +8,7 @@ publish = false
[dependencies] [dependencies]
apply = "0.3.0" apply = "0.3.0"
fraction = "0.15.3" fraction = "0.15.3"
libcosmic = { path = "../..", features = [ libcosmic-yoda = { path = "../..", features = [
"debug", "debug",
"winit", "winit",
"tokio", "tokio",

View file

@ -7,6 +7,6 @@ edition = "2021"
tracing = "0.1.44" tracing = "0.1.44"
tracing-subscriber = "0.3.22" tracing-subscriber = "0.3.22"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
path = "../../" path = "../../"
features = ["debug", "winit", "wgpu", "tokio"] features = ["debug", "winit", "wgpu", "tokio"]

View file

@ -8,6 +8,6 @@ tracing = "0.1.44"
tracing-subscriber = "0.3.22" tracing-subscriber = "0.3.22"
tracing-log = "0.2.0" tracing-log = "0.2.0"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
path = "../../" path = "../../"
features = ["debug", "winit", "tokio", "xdg-portal", "wgpu"] features = ["debug", "winit", "tokio", "xdg-portal", "wgpu"]

View file

@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
libcosmic = { path = "../..", features = ["debug", "winit", "tokio", "single-instance", "wgpu", "wayland"] } libcosmic-yoda = { path = "../..", features = ["debug", "winit", "tokio", "single-instance", "wgpu", "wayland"] }

View file

@ -8,6 +8,6 @@ tracing = "0.1.44"
tracing-subscriber = "0.3.22" tracing-subscriber = "0.3.22"
tracing-log = "0.2.0" tracing-log = "0.2.0"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
path = "../../" path = "../../"
features = ["debug", "winit", "tokio", "xdg-portal", "wgpu"] features = ["debug", "winit", "tokio", "xdg-portal", "wgpu"]

View file

@ -5,8 +5,8 @@ edition = "2021"
[features] [features]
default = ["xdg-portal"] default = ["xdg-portal"]
rfd = ["libcosmic/rfd"] rfd = ["libcosmic-yoda/rfd"]
xdg-portal = ["libcosmic/xdg-portal"] xdg-portal = ["libcosmic-yoda/xdg-portal"]
[dependencies] [dependencies]
apply = "0.3.0" apply = "0.3.0"
@ -15,6 +15,6 @@ tracing = "0.1.44"
tracing-subscriber = "0.3.22" tracing-subscriber = "0.3.22"
url = "2.5.8" url = "2.5.8"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
features = ["debug", "winit", "wgpu", "wayland", "tokio"] features = ["debug", "winit", "wgpu", "wayland", "tokio"]
path = "../../" path = "../../"

View file

@ -6,7 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
fraction = "0.15.3" fraction = "0.15.3"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
features = ["debug", "wgpu", "winit", "desktop", "tokio"] features = ["debug", "wgpu", "winit", "desktop", "tokio"]
path = "../.." path = "../.."
default-features = false default-features = false

View file

@ -5,6 +5,6 @@ edition = "2024"
[dependencies] [dependencies]
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
path = "../../" path = "../../"
features = ["debug", "winit", "wgpu", "tokio", "xdg-portal"] features = ["debug", "winit", "wgpu", "tokio", "xdg-portal"]

View file

@ -9,6 +9,6 @@ tracing-subscriber = "0.3.22"
tracing-log = "0.2.0" tracing-log = "0.2.0"
chrono = "*" chrono = "*"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
features = ["debug", "wgpu", "winit", "desktop", "tokio"] features = ["debug", "wgpu", "winit", "desktop", "tokio"]
path = "../.." path = "../.."

View file

@ -8,6 +8,6 @@ tracing = "0.1.44"
tracing-subscriber = "0.3.22" tracing-subscriber = "0.3.22"
tracing-log = "0.2.0" tracing-log = "0.2.0"
[dependencies.libcosmic] [dependencies.libcosmic-yoda]
path = "../../" path = "../../"
features = ["debug", "winit", "wgpu", "tokio", "xdg-portal"] features = ["debug", "winit", "wgpu", "tokio", "xdg-portal"]

2
iced

@ -1 +1 @@
Subproject commit 62b90179a298b06ed3e88362e08ef47f8557da27 Subproject commit d9fe129f7316cea3ef6d2576e9421a305759b8bf

View file

@ -1,7 +1,6 @@
// Copyright 2023 System76 <info@system76.com> // Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
#[cfg(feature = "winit")]
use crate::app; use crate::app;
#[cfg(feature = "single-instance")] #[cfg(feature = "single-instance")]
use crate::dbus_activation; use crate::dbus_activation;
@ -9,7 +8,6 @@ use crate::dbus_activation;
pub const fn app<M>(message: M) -> Action<M> { pub const fn app<M>(message: M) -> Action<M> {
Action::App(message) Action::App(message)
} }
#[cfg(feature = "winit")]
pub const fn cosmic<M>(message: app::Action) -> Action<M> { pub const fn cosmic<M>(message: app::Action) -> Action<M> {
Action::Cosmic(message) Action::Cosmic(message)
} }
@ -23,7 +21,6 @@ pub const fn none<M>() -> Action<M> {
pub enum Action<M> { pub enum Action<M> {
/// Messages from the application, for the application. /// Messages from the application, for the application.
App(M), App(M),
#[cfg(feature = "winit")]
/// Internal messages to be handled by libcosmic. /// Internal messages to be handled by libcosmic.
Cosmic(app::Action), Cosmic(app::Action),
#[cfg(feature = "single-instance")] #[cfg(feature = "single-instance")]

View file

@ -100,9 +100,10 @@ impl<T: Application> Cosmic<T>
where where
T::Message: Send + 'static, T::Message: Send + 'static,
{ {
pub fn init( pub fn init((core, flags): (Core, T::Flags)) -> (Self, iced::Task<crate::Action<T::Message>>) {
(mut core, flags): (Core, T::Flags), #[cfg(all(feature = "dbus-config", target_os = "linux"))]
) -> (Self, iced::Task<crate::Action<T::Message>>) { let mut core = core;
#[cfg(all(feature = "dbus-config", target_os = "linux"))] #[cfg(all(feature = "dbus-config", target_os = "linux"))]
{ {
use iced_futures::futures::executor::block_on; use iced_futures::futures::executor::block_on;
@ -364,7 +365,6 @@ where
crate::surface::Action::Task(f) => { crate::surface::Action::Task(f) => {
f().map(|sm| crate::Action::Cosmic(Action::Surface(sm))) f().map(|sm| crate::Action::Cosmic(Action::Surface(sm)))
} }
_ => iced::Task::none(),
} }
#[cfg(not(feature = "surface-message"))] #[cfg(not(feature = "surface-message"))]
@ -408,7 +408,7 @@ where
f64::from(self.app.core().scale_factor()) f64::from(self.app.core().scale_factor())
} }
pub fn style(&self, theme: &Theme) -> theme::Style { pub fn style(&self, _theme: &Theme) -> theme::Style {
if let Some(style) = self.app.style() { if let Some(style) = self.app.style() {
style style
} else if self.app.core().window.is_maximized { } else if self.app.core().window.is_maximized {
@ -480,12 +480,11 @@ where
.into_iter() .into_iter()
.filter(cosmic_config::Error::is_err) .filter(cosmic_config::Error::is_err)
{ {
if let cosmic_config::Error::GetKey(_, err) = &why { if let cosmic_config::Error::GetKey(_, err) = &why
if err.kind() == std::io::ErrorKind::NotFound { && err.kind() == std::io::ErrorKind::NotFound {
// No system default config installed; don't error // No system default config installed; don't error
continue; continue;
} }
}
tracing::error!(?why, "cosmic toolkit config update error"); tracing::error!(?why, "cosmic toolkit config update error");
} }
@ -621,15 +620,15 @@ impl<T: Application> Cosmic<T> {
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
fn cosmic_update(&mut self, message: Action) -> iced::Task<crate::Action<T::Message>> { fn cosmic_update(&mut self, message: Action) -> iced::Task<crate::Action<T::Message>> {
match message { match message {
Action::WindowMaximized(id, maximized) => { Action::WindowMaximized(_id, _maximized) => {
#[cfg(not(all(feature = "wayland", target_os = "linux")))] #[cfg(not(all(feature = "wayland", target_os = "linux")))]
if self if self
.app .app
.core() .core()
.main_window_id() .main_window_id()
.is_some_and(|main_id| main_id == id) .is_some_and(|main_id| main_id == _id)
{ {
self.app.core_mut().window.sharp_corners = maximized; self.app.core_mut().window.sharp_corners = _maximized;
} }
} }

View file

@ -136,7 +136,7 @@ pub fn run<App: Application>(settings: Settings, flags: App::Flags) -> iced::Res
crate::malloc::limit_mmap_threshold(threshold); crate::malloc::limit_mmap_threshold(threshold);
} }
let default_font = settings.default_font; let _default_font = settings.default_font;
let (settings, (mut core, flags), window_settings) = iced_settings::<App>(settings, flags); let (settings, (mut core, flags), window_settings) = iced_settings::<App>(settings, flags);
#[cfg(not(feature = "multi-window"))] #[cfg(not(feature = "multi-window"))]
{ {
@ -284,7 +284,7 @@ where
// app = app.window(window_settings); // app = app.window(window_settings);
core.main_window = Some(iced_core::window::Id::RESERVED); core.main_window = Some(iced_core::window::Id::RESERVED);
} }
let mut app = iced::daemon( let app = iced::daemon(
BootData(Rc::new(RefCell::new(Some(BootDataInner::<App> { BootData(Rc::new(RefCell::new(Some(BootDataInner::<App> {
flags, flags,
core, core,

View file

@ -1,14 +1,13 @@
//! Distribute content horizontally. //! Distribute content horizontally.
use crate::iced; use crate::iced;
use iced::core::alignment::{self, Alignment}; use iced::core::alignment::{self, Alignment};
use iced::core::event::{self, Event}; use iced::core::event::Event;
use iced::core::layout::{self, Layout}; use iced::core::layout::{self, Layout};
use iced::core::widget::{Operation, Tree}; use iced::core::widget::{Operation, Tree};
use iced::core::{ use iced::core::{
Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, Widget, mouse, Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, Widget, mouse,
overlay, renderer, widget, overlay, renderer, widget,
}; };
use iced::touch;
/// A container that distributes its contents horizontally. /// A container that distributes its contents horizontally.
/// ///

View file

@ -27,12 +27,10 @@ pub fn set_title<M>(id: window::Id, title: String) -> iced::Task<crate::Action<M
iced::Task::none() iced::Task::none()
} }
#[cfg(feature = "winit")]
pub fn set_scaling_factor<M: Send + 'static>(factor: f32) -> iced::Task<crate::Action<M>> { pub fn set_scaling_factor<M: Send + 'static>(factor: f32) -> iced::Task<crate::Action<M>> {
iced::Task::done(crate::app::Action::ScaleFactor(factor)).map(crate::Action::Cosmic) iced::Task::done(crate::app::Action::ScaleFactor(factor)).map(crate::Action::Cosmic)
} }
#[cfg(feature = "winit")]
pub fn set_theme<M: Send + 'static>(theme: crate::Theme) -> iced::Task<crate::Action<M>> { pub fn set_theme<M: Send + 'static>(theme: crate::Theme) -> iced::Task<crate::Action<M>> {
iced::Task::done(crate::app::Action::AppThemeChange(theme)).map(crate::Action::Cosmic) iced::Task::done(crate::app::Action::AppThemeChange(theme)).map(crate::Action::Cosmic)
} }

View file

@ -4,6 +4,7 @@
//! Configurations available to libcosmic applications. //! Configurations available to libcosmic applications.
use crate::cosmic_theme::Density; use crate::cosmic_theme::Density;
use crate::widget::WindowControlsPosition;
use cosmic_config::cosmic_config_derive::CosmicConfigEntry; use cosmic_config::cosmic_config_derive::CosmicConfigEntry;
use cosmic_config::{Config, CosmicConfigEntry}; use cosmic_config::{Config, CosmicConfigEntry};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -22,12 +23,11 @@ pub static COSMIC_TK: LazyLock<RwLock<CosmicTk>> = LazyLock::new(|| {
.map(|c| { .map(|c| {
CosmicTk::get_entry(&c).unwrap_or_else(|(errors, mode)| { CosmicTk::get_entry(&c).unwrap_or_else(|(errors, mode)| {
for why in errors.into_iter().filter(cosmic_config::Error::is_err) { for why in errors.into_iter().filter(cosmic_config::Error::is_err) {
if let cosmic_config::Error::GetKey(_, err) = &why { if let cosmic_config::Error::GetKey(_, err) = &why
if err.kind() == std::io::ErrorKind::NotFound { && err.kind() == std::io::ErrorKind::NotFound {
// No system default config installed; don't error // No system default config installed; don't error
continue; continue;
} }
}
tracing::error!(?why, "CosmicTk config entry error"); tracing::error!(?why, "CosmicTk config entry error");
} }
mode mode
@ -67,6 +67,12 @@ pub fn header_size() -> Density {
COSMIC_TK.read().unwrap().header_size COSMIC_TK.read().unwrap().header_size
} }
/// Position of the window control buttons (close / minimize / maximize).
#[allow(clippy::missing_panics_doc)]
pub fn window_controls_position() -> WindowControlsPosition {
COSMIC_TK.read().unwrap().window_controls_position
}
/// Interface density. /// Interface density.
#[allow(clippy::missing_panics_doc)] #[allow(clippy::missing_panics_doc)]
pub fn interface_density() -> Density { pub fn interface_density() -> Density {
@ -109,6 +115,10 @@ pub struct CosmicTk {
/// Mono font family /// Mono font family
pub monospace_font: FontConfig, pub monospace_font: FontConfig,
/// Side on which window control buttons (close / minimize / maximize)
/// are placed. `End` = right (Linux / GNOME), `Start` = left (macOS).
pub window_controls_position: WindowControlsPosition,
} }
impl Default for CosmicTk { impl Default for CosmicTk {
@ -132,6 +142,7 @@ impl Default for CosmicTk {
stretch: iced::font::Stretch::Normal, stretch: iced::font::Stretch::Normal,
style: iced::font::Style::Normal, style: iced::font::Style::Normal,
}, },
window_controls_position: WindowControlsPosition::default(),
} }
} }
} }

View file

@ -78,8 +78,6 @@ pub struct Core {
pub(super) portal_accent: Option<Srgba>, pub(super) portal_accent: Option<Srgba>,
pub(super) portal_is_high_contrast: Option<bool>,
pub(super) title: HashMap<Id, String>, pub(super) title: HashMap<Id, String>,
pub window: Window, pub window: Window,
@ -155,7 +153,6 @@ impl Default for Core {
settings_daemon: None, settings_daemon: None,
portal_is_dark: None, portal_is_dark: None,
portal_accent: None, portal_accent: None,
portal_is_high_contrast: None,
main_window: None, main_window: None,
exit_on_main_window_closed: true, exit_on_main_window_closed: true,
menu_bars: HashMap::new(), menu_bars: HashMap::new(),
@ -432,7 +429,6 @@ impl Core {
id id
} }
#[cfg(feature = "winit")]
pub fn drag<M: Send + 'static>(&self, id: Option<window::Id>) -> crate::app::Task<M> { pub fn drag<M: Send + 'static>(&self, id: Option<window::Id>) -> crate::app::Task<M> {
let Some(id) = id.or(self.main_window) else { let Some(id) = id.or(self.main_window) else {
return iced::Task::none(); return iced::Task::none();
@ -440,7 +436,6 @@ impl Core {
crate::command::drag(id) crate::command::drag(id)
} }
#[cfg(feature = "winit")]
pub fn maximize<M: Send + 'static>( pub fn maximize<M: Send + 'static>(
&self, &self,
id: Option<window::Id>, id: Option<window::Id>,
@ -452,7 +447,6 @@ impl Core {
crate::command::maximize(id, maximized) crate::command::maximize(id, maximized)
} }
#[cfg(feature = "winit")]
pub fn minimize<M: Send + 'static>(&self, id: Option<window::Id>) -> crate::app::Task<M> { pub fn minimize<M: Send + 'static>(&self, id: Option<window::Id>) -> crate::app::Task<M> {
let Some(id) = id.or(self.main_window) else { let Some(id) = id.or(self.main_window) else {
return iced::Task::none(); return iced::Task::none();
@ -460,7 +454,6 @@ impl Core {
crate::command::minimize(id) crate::command::minimize(id)
} }
#[cfg(feature = "winit")]
pub fn set_title<M: Send + 'static>( pub fn set_title<M: Send + 'static>(
&self, &self,
id: Option<window::Id>, id: Option<window::Id>,
@ -472,7 +465,6 @@ impl Core {
crate::command::set_title(id, title) crate::command::set_title(id, title)
} }
#[cfg(feature = "winit")]
pub fn set_windowed<M: Send + 'static>(&self, id: Option<window::Id>) -> crate::app::Task<M> { pub fn set_windowed<M: Send + 'static>(&self, id: Option<window::Id>) -> crate::app::Task<M> {
let Some(id) = id.or(self.main_window) else { let Some(id) = id.or(self.main_window) else {
return iced::Task::none(); return iced::Task::none();
@ -480,7 +472,6 @@ impl Core {
crate::command::set_windowed(id) crate::command::set_windowed(id)
} }
#[cfg(feature = "winit")]
pub fn toggle_maximize<M: Send + 'static>( pub fn toggle_maximize<M: Send + 'static>(
&self, &self,
id: Option<window::Id>, id: Option<window::Id>,

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