Prepare 0.1.0-beta.2 feature freeze and release validation
This commit is contained in:
1 parent
a62f1367bd
commit
77fa25e5f7
14 files changed
+202
-145
No files matched your search
Generated
+18
-18
@@ -1848,7 +1848,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese"
|
name = "ferese"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ab_glyph",
|
"ab_glyph",
|
||||||
"async-channel",
|
"async-channel",
|
||||||
@@ -1881,14 +1881,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-activities"
|
name = "ferese-activities"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-animation"
|
name = "ferese-animation"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ferese-layout",
|
"ferese-layout",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -1896,7 +1896,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-config"
|
name = "ferese-config"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ferese-activities",
|
"ferese-activities",
|
||||||
"ferese-panel",
|
"ferese-panel",
|
||||||
@@ -1911,7 +1911,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-core"
|
name = "ferese-core"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ferese-layout",
|
"ferese-layout",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -1919,7 +1919,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-ipc"
|
name = "ferese-ipc"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ferese-activities",
|
"ferese-activities",
|
||||||
"ferese-theme-model",
|
"ferese-theme-model",
|
||||||
@@ -1930,11 +1930,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-layout"
|
name = "ferese-layout"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-lock"
|
name = "ferese-lock"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ferese-config",
|
"ferese-config",
|
||||||
"ferese-ipc",
|
"ferese-ipc",
|
||||||
@@ -1954,7 +1954,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-panel"
|
name = "ferese-panel"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ferese-animation",
|
"ferese-animation",
|
||||||
"ferese-layout",
|
"ferese-layout",
|
||||||
@@ -1964,7 +1964,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-polkit-agent"
|
name = "ferese-polkit-agent"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ferese-config",
|
"ferese-config",
|
||||||
"ferese-ipc",
|
"ferese-ipc",
|
||||||
@@ -1983,7 +1983,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-protocols"
|
name = "ferese-protocols"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.2",
|
"bitflags 2.13.2",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
@@ -1995,7 +1995,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-settings"
|
name = "ferese-settings"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ferese-config",
|
"ferese-config",
|
||||||
"ferese-ipc",
|
"ferese-ipc",
|
||||||
@@ -2021,7 +2021,7 @@ source = "git+https://github.com/ferese-wm/ferese-shape?tag=v0.1.0#63d7b6dfd520d
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-shell"
|
name = "ferese-shell"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"ferese-activities",
|
"ferese-activities",
|
||||||
@@ -2055,7 +2055,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-theme"
|
name = "ferese-theme"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ferese-config",
|
"ferese-config",
|
||||||
"ferese-layout",
|
"ferese-layout",
|
||||||
@@ -2069,7 +2069,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-theme-client"
|
name = "ferese-theme-client"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ferese-config",
|
"ferese-config",
|
||||||
"ferese-ipc",
|
"ferese-ipc",
|
||||||
@@ -2083,14 +2083,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ferese-theme-model"
|
name = "ferese-theme-model"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "feresectl"
|
name = "feresectl"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"ferese-activities",
|
"ferese-activities",
|
||||||
@@ -8249,7 +8249,7 @@ checksum = "2fb433233f2df9344722454bc7e96465c9d03bff9d77c248f9e7523fe79585b5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xdg-desktop-portal-ferese"
|
name = "xdg-desktop-portal-ferese"
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"calloop 0.14.4",
|
"calloop 0.14.4",
|
||||||
"dirs 6.0.0",
|
"dirs 6.0.0",
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ members = [
|
|||||||
resolver = "3"
|
resolver = "3"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.0-beta"
|
version = "0.1.0-beta.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
rust-version = "1.95"
|
rust-version = "1.95"
|
||||||
|
|||||||
@@ -886,10 +886,10 @@ impl Ferese {
|
|||||||
let Some(surface) = self.seat.get_keyboard().and_then(|keyboard| keyboard.current_focus()) else {
|
let Some(surface) = self.seat.get_keyboard().and_then(|keyboard| keyboard.current_focus()) else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
if !self
|
if self
|
||||||
.space
|
.space
|
||||||
.layer_for_surface(&surface, smithay::desktop::WindowSurfaceType::ALL)
|
.layer_for_surface(&surface, smithay::desktop::WindowSurfaceType::ALL)
|
||||||
.is_some_and(|layer| layer.namespace() == "ferese-launcher")
|
.is_none_or(|layer| layer.namespace() != "ferese-launcher")
|
||||||
|| self
|
|| self
|
||||||
.layer_under(location)
|
.layer_under(location)
|
||||||
.is_some_and(|(layer, _, _)| layer.wl_surface() == &surface)
|
.is_some_and(|(layer, _, _)| layer.wl_surface() == &surface)
|
||||||
|
|||||||
@@ -703,6 +703,79 @@ fn send_request_failed(shell: &FereseShellV1, request: ferese_shell_v1::FailedRe
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ferese {
|
||||||
|
pub(crate) fn dismiss_launcher(&self) {
|
||||||
|
for shell in self
|
||||||
|
.shell_resources
|
||||||
|
.iter()
|
||||||
|
.filter_map(|s| s.upgrade().ok())
|
||||||
|
.filter(|s| s.version() >= 10)
|
||||||
|
{
|
||||||
|
shell.dismiss_launcher();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shell_thumbnail(&mut self, id: WindowId) -> Option<(u32, u32, std::fs::File)> {
|
||||||
|
use std::io::{Seek, Write};
|
||||||
|
if self.session_lock.active() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let window = self
|
||||||
|
.windows
|
||||||
|
.ids()
|
||||||
|
.iter()
|
||||||
|
.find(|(_, candidate)| **candidate == id)?
|
||||||
|
.0
|
||||||
|
.clone();
|
||||||
|
if self.capture_protected(&window) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let workspace = self.workspaces.workspace_for_window(id)?;
|
||||||
|
let owner = self.output_workspaces.output_for_workspace(workspace)?;
|
||||||
|
let output = self
|
||||||
|
.output_ids
|
||||||
|
.iter()
|
||||||
|
.find(|(_, candidate)| **candidate == owner)?
|
||||||
|
.0
|
||||||
|
.clone();
|
||||||
|
let geometry = window.geometry();
|
||||||
|
if geometry.size.w <= 0 || geometry.size.h <= 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let scale = (320. / f64::from(geometry.size.w))
|
||||||
|
.min(168. / f64::from(geometry.size.h))
|
||||||
|
.min(1.);
|
||||||
|
let result = if let Some(backend) = self.nested_backend.clone() {
|
||||||
|
let mut backend = backend.try_borrow_mut().ok()?;
|
||||||
|
crate::render::capture_window_frame(backend.renderer(), &window, geometry, scale, None)
|
||||||
|
} else {
|
||||||
|
let mut backend = self.direct_backend.take()?;
|
||||||
|
let result = backend.capture_window_frame(self, &window, &output, None, scale);
|
||||||
|
self.direct_backend = Some(backend);
|
||||||
|
result
|
||||||
|
};
|
||||||
|
let mut buffer = result.ok()?;
|
||||||
|
if buffer.width <= 0 || buffer.width > 320 || buffer.height <= 0 || buffer.height > 168 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
// GL ABGR readback is RGBA bytes on the supported little-endian targets.
|
||||||
|
// Iced expects straight rather than premultiplied channels.
|
||||||
|
for pixel in buffer.pixels.chunks_exact_mut(4) {
|
||||||
|
let alpha = u16::from(pixel[3]);
|
||||||
|
for channel in &mut pixel[..3] {
|
||||||
|
*channel = (u16::from(*channel) * 255 + alpha / 2)
|
||||||
|
.checked_div(alpha)
|
||||||
|
.unwrap_or(0)
|
||||||
|
.min(255) as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut file = tempfile::tempfile().ok()?;
|
||||||
|
file.write_all(&buffer.pixels).ok()?;
|
||||||
|
file.rewind().ok()?;
|
||||||
|
Some((buffer.width as u32, buffer.height as u32, file))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
@@ -916,76 +989,3 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ferese {
|
|
||||||
pub(crate) fn dismiss_launcher(&self) {
|
|
||||||
for shell in self
|
|
||||||
.shell_resources
|
|
||||||
.iter()
|
|
||||||
.filter_map(|s| s.upgrade().ok())
|
|
||||||
.filter(|s| s.version() >= 10)
|
|
||||||
{
|
|
||||||
shell.dismiss_launcher();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn shell_thumbnail(&mut self, id: WindowId) -> Option<(u32, u32, std::fs::File)> {
|
|
||||||
use std::io::{Seek, Write};
|
|
||||||
if self.session_lock.active() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let window = self
|
|
||||||
.windows
|
|
||||||
.ids()
|
|
||||||
.iter()
|
|
||||||
.find(|(_, candidate)| **candidate == id)?
|
|
||||||
.0
|
|
||||||
.clone();
|
|
||||||
if self.capture_protected(&window) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let workspace = self.workspaces.workspace_for_window(id)?;
|
|
||||||
let owner = self.output_workspaces.output_for_workspace(workspace)?;
|
|
||||||
let output = self
|
|
||||||
.output_ids
|
|
||||||
.iter()
|
|
||||||
.find(|(_, candidate)| **candidate == owner)?
|
|
||||||
.0
|
|
||||||
.clone();
|
|
||||||
let geometry = window.geometry();
|
|
||||||
if geometry.size.w <= 0 || geometry.size.h <= 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let scale = (320. / f64::from(geometry.size.w))
|
|
||||||
.min(168. / f64::from(geometry.size.h))
|
|
||||||
.min(1.);
|
|
||||||
let result = if let Some(backend) = self.nested_backend.clone() {
|
|
||||||
let mut backend = backend.try_borrow_mut().ok()?;
|
|
||||||
crate::render::capture_window_frame(backend.renderer(), &window, geometry, scale, None)
|
|
||||||
} else {
|
|
||||||
let mut backend = self.direct_backend.take()?;
|
|
||||||
let result = backend.capture_window_frame(self, &window, &output, None, scale);
|
|
||||||
self.direct_backend = Some(backend);
|
|
||||||
result
|
|
||||||
};
|
|
||||||
let mut buffer = result.ok()?;
|
|
||||||
if buffer.width <= 0 || buffer.width > 320 || buffer.height <= 0 || buffer.height > 168 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
// GL ABGR readback is RGBA bytes on the supported little-endian targets.
|
|
||||||
// Iced expects straight rather than premultiplied channels.
|
|
||||||
for pixel in buffer.pixels.chunks_exact_mut(4) {
|
|
||||||
let alpha = u16::from(pixel[3]);
|
|
||||||
for channel in &mut pixel[..3] {
|
|
||||||
*channel = (u16::from(*channel) * 255 + alpha / 2)
|
|
||||||
.checked_div(alpha)
|
|
||||||
.unwrap_or(0)
|
|
||||||
.min(255) as u8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut file = tempfile::tempfile().ok()?;
|
|
||||||
file.write_all(&buffer.pixels).ok()?;
|
|
||||||
file.rewind().ok()?;
|
|
||||||
Some((buffer.width as u32, buffer.height as u32, file))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -40,6 +40,7 @@ and [guides at that tag](https://github.com/ferese-wm/ferese/tree/v0.1.0-beta/do
|
|||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
- [0.1.0-beta.2 preparation](releases/0.1.0-beta.2.md): feature freeze, changes and validation gates.
|
||||||
- [Packages and releases](packaging.md): build Fedora and Arch packages and publish a tagged release.
|
- [Packages and releases](packaging.md): build Fedora and Arch packages and publish a tagged release.
|
||||||
- [Development](development.md): build Ferese, run tests and check portal contracts.
|
- [Development](development.md): build Ferese, run tests and check portal contracts.
|
||||||
- [Publishing activities](development/activities.md): IPC schema, ownership, limits and templates.
|
- [Publishing activities](development/activities.md): IPC schema, ownership, limits and templates.
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# 0.1.0-beta.2 preparation
|
||||||
|
|
||||||
|
The 0.1.0 feature set is frozen as of October 14, 2026. Changes after the freeze
|
||||||
|
are limited to regression fixes, release preparation and documentation.
|
||||||
|
Beta 2 is being validated. It has not been released.
|
||||||
|
|
||||||
|
## Changes since 0.1.0-beta
|
||||||
|
|
||||||
|
- Native launcher with app, file and window search, category browsing and theme support.
|
||||||
|
- Panel styles, the Morph hub and configurable Live Activities.
|
||||||
|
- Tabbed window groups and named keyboard binding modes.
|
||||||
|
- Night light, animated temperature changes and brightness shortcuts on the lock screen.
|
||||||
|
- Window blur controls and reorganized Settings pages.
|
||||||
|
- Region recording with audio, fractional-scale capture fixes and idle capture-cache cleanup.
|
||||||
|
- Complete CRTC matching, bounded resize waits and output-specific DMA-BUF feedback.
|
||||||
|
- Layer and popup focus fixes, managed-window activation and outside-launcher touch dismissal.
|
||||||
|
- Security-context filtering for both privileged clipboard protocols. Ordinary clipboard
|
||||||
|
access remains available, and host clipboard tools retain data-control access.
|
||||||
|
|
||||||
|
## Release gates
|
||||||
|
|
||||||
|
Record the full candidate commit with each log, artifact and hardware report.
|
||||||
|
If a fix changes the candidate, rerun validation on the new commit before tagging.
|
||||||
|
|
||||||
|
- [x] Freeze the 0.1.0 feature set.
|
||||||
|
- [x] Set the workspace and lockfile version to `0.1.0-beta.2` and prepare release notes.
|
||||||
|
- [ ] Pass formatting and Clippy with warnings denied.
|
||||||
|
- [ ] Pass workspace tests, capture and recorder checks, Python tests and headless integration tests.
|
||||||
|
- [ ] Build Fedora 44 RPMs and Arch packages from the same candidate.
|
||||||
|
- [ ] Validate direct DRM: login/logout, locking, suspend/resume, lid and monitor changes,
|
||||||
|
fullscreen, screenshots and screen sharing.
|
||||||
|
- [ ] Test fresh Fedora 44 and Arch installs and upgrades from `0.1.0-beta`.
|
||||||
|
Check existing configurations, PAM, services and display-manager session selection.
|
||||||
|
- [ ] Pass native soak runs with crash, RSS, file-descriptor and client-exit recovery checks.
|
||||||
|
- [ ] Resolve release blockers, attach validation evidence and publish the tested candidate.
|
||||||
|
|
||||||
|
## Validation procedure
|
||||||
|
|
||||||
|
Use the **Release packages** workflow's manual dispatch on the candidate branch.
|
||||||
|
It runs release checks and builds both package formats. Confirm that the run's
|
||||||
|
`headSha` matches the candidate. Manual dispatch does not publish a release.
|
||||||
|
|
||||||
|
For local checks, follow [Development](../development.md). Use the
|
||||||
|
[native soak runner](../native-soak-testing.md) in a disposable session and retain
|
||||||
|
its declared duration and resource budgets with the results. A short smoke run
|
||||||
|
does not satisfy the full soak gate.
|
||||||
|
|
||||||
|
Package builds alone do not establish install or upgrade compatibility.
|
||||||
|
Record the distribution, package version, configuration changes and session results
|
||||||
|
for each fresh install and upgrade. Hardware reports also need the GPU, driver,
|
||||||
|
kernel and monitor setup.
|
||||||
|
|
||||||
|
The reported login flash still needs reproduction on the candidate. The bar's
|
||||||
|
initial material publication was changed, but the separate info-modal report
|
||||||
|
has not been confirmed. DMA-BUF refresh cost also remains unprofiled.
|
||||||
@@ -26,17 +26,20 @@ impl FereseShell {
|
|||||||
} else {
|
} else {
|
||||||
foreground
|
foreground
|
||||||
};
|
};
|
||||||
let fill = container(Space::new().width((BODY_WIDTH - 4.) * f32::from(percent) / 100.).height(10)).class(
|
let fill = container(
|
||||||
theme::Container::custom(move |_| container::Style {
|
Space::new()
|
||||||
background: Some(Background::Color(outline.scale_alpha(0.16))),
|
.width((BODY_WIDTH - 4.) * f32::from(percent) / 100.)
|
||||||
border: Border {
|
.height(10),
|
||||||
shape: cosmic::iced::border::Shape::Continuous,
|
)
|
||||||
radius: 4.0.into(),
|
.class(theme::Container::custom(move |_| container::Style {
|
||||||
..Default::default()
|
background: Some(Background::Color(outline.scale_alpha(0.16))),
|
||||||
},
|
border: Border {
|
||||||
|
shape: cosmic::iced::border::Shape::Continuous,
|
||||||
|
radius: 4.0.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
},
|
||||||
);
|
..Default::default()
|
||||||
|
}));
|
||||||
let number = self
|
let number = self
|
||||||
.render
|
.render
|
||||||
.text(if show_percentage {
|
.text(if show_percentage {
|
||||||
@@ -72,9 +75,6 @@ impl FereseShell {
|
|||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
row![body, terminal]
|
row![body, terminal].spacing(1).align_y(Alignment::Center).into()
|
||||||
.spacing(1)
|
|
||||||
.align_y(Alignment::Center)
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,10 +18,10 @@ pub(super) fn run(target: Target, terminal: &[String]) -> Result<(), String> {
|
|||||||
} else {
|
} else {
|
||||||
open("gio", &[std::ffi::OsStr::new("launch"), desktop.as_os_str()])
|
open("gio", &[std::ffi::OsStr::new("launch"), desktop.as_os_str()])
|
||||||
};
|
};
|
||||||
if result.is_ok() {
|
if result.is_ok()
|
||||||
if let Err(error) = apps::record(&id) {
|
&& let Err(error) = apps::record(&id)
|
||||||
eprintln!("Could not save launcher history: {error}");
|
{
|
||||||
}
|
eprintln!("Could not save launcher history: {error}");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -464,12 +464,14 @@ impl FereseShell {
|
|||||||
if launcher.closing && !launcher.progress.is_animating() {
|
if launcher.closing && !launcher.progress.is_animating() {
|
||||||
return self.finish_launcher();
|
return self.finish_launcher();
|
||||||
}
|
}
|
||||||
if !launcher.closing && launcher.query.is_empty() && launcher.category == Some(Category::Windows) {
|
if !launcher.closing
|
||||||
if let Some(control) = &self.control {
|
&& launcher.query.is_empty()
|
||||||
launcher
|
&& launcher.category == Some(Category::Windows)
|
||||||
.thumbnails
|
&& let Some(control) = &self.control
|
||||||
.refresh(&launcher.rows, launcher.selected, control, now);
|
{
|
||||||
}
|
launcher
|
||||||
|
.thumbnails
|
||||||
|
.refresh(&launcher.rows, launcher.selected, control, now);
|
||||||
}
|
}
|
||||||
if !launcher.closing
|
if !launcher.closing
|
||||||
&& now.duration_since(launcher.refresh) >= Duration::from_secs(1)
|
&& now.duration_since(launcher.refresh) >= Duration::from_secs(1)
|
||||||
|
|||||||
@@ -177,9 +177,10 @@ impl FereseShell {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
strip = strip.push(
|
strip = strip.push(
|
||||||
button::custom(
|
button::custom(crate::bar_content(
|
||||||
crate::bar_content(self.battery_indicator(self.config.theme, opacity, true), 28.)
|
self.battery_indicator(self.config.theme, opacity, true),
|
||||||
)
|
28.,
|
||||||
|
))
|
||||||
.name(format!("Low battery, {percent} percent. Open battery controls"))
|
.name(format!("Low battery, {percent} percent. Open battery controls"))
|
||||||
.padding(0)
|
.padding(0)
|
||||||
.height(28)
|
.height(28)
|
||||||
|
|||||||
@@ -15,15 +15,18 @@ impl FereseShell {
|
|||||||
let foreground = color_with_opacity(self.config.theme.text_primary, opacity);
|
let foreground = color_with_opacity(self.config.theme.text_primary, opacity);
|
||||||
Some(motion::button(
|
Some(motion::button(
|
||||||
self.render,
|
self.render,
|
||||||
button::custom(crate::bar_content(self.battery_indicator(self.config.theme, opacity, true), 28.))
|
button::custom(crate::bar_content(
|
||||||
.name(format!(
|
self.battery_indicator(self.config.theme, opacity, true),
|
||||||
"Battery, {percent} percent, {}. Open battery controls",
|
28.,
|
||||||
battery.status
|
))
|
||||||
))
|
.name(format!(
|
||||||
.padding([0, 3])
|
"Battery, {percent} percent, {}. Open battery controls",
|
||||||
.width(WIDTH as f32)
|
battery.status
|
||||||
.height(28)
|
))
|
||||||
.on_press(cosmic::Action::App(Message::HubOpen(id, status_ui::Menu::Battery))),
|
.padding([0, 3])
|
||||||
|
.width(WIDTH as f32)
|
||||||
|
.height(28)
|
||||||
|
.on_press(cosmic::Action::App(Message::HubOpen(id, status_ui::Menu::Battery))),
|
||||||
foreground,
|
foreground,
|
||||||
active,
|
active,
|
||||||
opacity,
|
opacity,
|
||||||
|
|||||||
@@ -377,12 +377,7 @@ impl FereseShell {
|
|||||||
.width(Length::Fixed(22.))
|
.width(Length::Fixed(22.))
|
||||||
.into()
|
.into()
|
||||||
};
|
};
|
||||||
let badge = ferese_theme::menus::badge(
|
let badge = ferese_theme::menus::badge(heading_icon, color(theme.accent), p, self.render.radius(20.));
|
||||||
heading_icon,
|
|
||||||
color(theme.accent),
|
|
||||||
p,
|
|
||||||
self.render.radius(20.),
|
|
||||||
);
|
|
||||||
let mut heading = ferese_theme::menus::heading(badge, kind.title(), self.render.font);
|
let mut heading = ferese_theme::menus::heading(badge, kind.title(), self.render.font);
|
||||||
let style = MenuStyle {
|
let style = MenuStyle {
|
||||||
theme,
|
theme,
|
||||||
|
|||||||
@@ -118,8 +118,12 @@ pub(super) fn view<'a>(
|
|||||||
container(shell.battery_indicator(theme, p, true))
|
container(shell.battery_indicator(theme, p, true))
|
||||||
.center_x(Length::Fill)
|
.center_x(Length::Fill)
|
||||||
.center_y(28),
|
.center_y(28),
|
||||||
shell.render.text("Battery").size(11)
|
shell
|
||||||
.width(Length::Fill).height(16)
|
.render
|
||||||
|
.text("Battery")
|
||||||
|
.size(11)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(16)
|
||||||
.align_x(alignment::Horizontal::Center)
|
.align_x(alignment::Horizontal::Center)
|
||||||
.class(theme::Text::Color(muted)),
|
.class(theme::Text::Color(muted)),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -461,7 +461,7 @@ impl FereseShell {
|
|||||||
Event::Window(window::Event::Closed) => {
|
Event::Window(window::Event::Closed) => {
|
||||||
self.closing_menu_effects.remove(&id);
|
self.closing_menu_effects.remove(&id);
|
||||||
Task::none()
|
Task::none()
|
||||||
},
|
}
|
||||||
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::Frame(_, surface, frame_id)))
|
Event::PlatformSpecific(PlatformSpecific::Wayland(wayland::Event::Frame(_, surface, frame_id)))
|
||||||
if self.menu.as_ref().is_some_and(|menu| menu.id == frame_id) =>
|
if self.menu.as_ref().is_some_and(|menu| menu.id == frame_id) =>
|
||||||
{
|
{
|
||||||
@@ -523,12 +523,8 @@ impl FereseShell {
|
|||||||
// The first panel presentation supplies the role and measured shape
|
// The first panel presentation supplies the role and measured shape
|
||||||
// together with its buffer. Enabling the role here would paint the
|
// together with its buffer. Enabling the role here would paint the
|
||||||
// whole surface before those bounds arrive.
|
// whole surface before those bounds arrive.
|
||||||
let binding = EffectsBinding::attach_role(
|
let binding =
|
||||||
&mut self.effects_context,
|
EffectsBinding::attach_role(&mut self.effects_context, surface, None, if hidden { 0.0 } else { 1.0 });
|
||||||
surface,
|
|
||||||
None,
|
|
||||||
if hidden { 0.0 } else { 1.0 },
|
|
||||||
);
|
|
||||||
|
|
||||||
match binding {
|
match binding {
|
||||||
Ok(binding) => entry.effects = Some(binding),
|
Ok(binding) => entry.effects = Some(binding),
|
||||||
|
|||||||
Reference in new issue
Block a user