Iced graphics applet (#26)
* feat: builds deb * feat: working iced graphics applet * fix: update deps to get fixes for iced-sctk * fix: better popup size * fix: better styling of button & popup * fix: better popup container * feat: sticky graphics mode after selection * fix: refactor & handle close requests
This commit is contained in:
parent
e3be1c1809
commit
eab7ddea1d
15 changed files with 3836 additions and 360 deletions
53
Cargo.lock
generated
53
Cargo.lock
generated
|
|
@ -384,20 +384,6 @@ dependencies = [
|
||||||
"zbus 2.3.2",
|
"zbus 2.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cosmic-applet-graphics"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"gtk4",
|
|
||||||
"libadwaita",
|
|
||||||
"libcosmic",
|
|
||||||
"libcosmic-applet",
|
|
||||||
"once_cell",
|
|
||||||
"relm4-macros",
|
|
||||||
"tokio",
|
|
||||||
"zbus 2.3.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cosmic-applet-network"
|
name = "cosmic-applet-network"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -1512,6 +1498,16 @@ dependencies = [
|
||||||
"unic-langid",
|
"unic-langid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "io-lifetimes"
|
||||||
|
version = "1.0.0-rc1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f65dae1d3aa98e6877917ab4e6fdbfdfb00e95885ea7c4f4f29e3a5dfc08fdf"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.10.3"
|
version = "0.10.3"
|
||||||
|
|
@ -2914,12 +2910,13 @@ checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-backend"
|
name = "wayland-backend"
|
||||||
version = "0.1.0-beta.9"
|
version = "0.1.0-beta.13"
|
||||||
source = "git+https://github.com/smithay/wayland-rs#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/smithay/wayland-rs#051cbf6e38f4532c74ab5fc9a8d39ed84e1f2e04"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
"nix 0.24.2",
|
"io-lifetimes",
|
||||||
|
"nix 0.25.0",
|
||||||
"scoped-tls",
|
"scoped-tls",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"wayland-sys",
|
"wayland-sys",
|
||||||
|
|
@ -2927,13 +2924,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-client"
|
name = "wayland-client"
|
||||||
version = "0.30.0-beta.9"
|
version = "0.30.0-beta.13"
|
||||||
source = "git+https://github.com/smithay/wayland-rs#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/smithay/wayland-rs#051cbf6e38f4532c74ab5fc9a8d39ed84e1f2e04"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"nix 0.24.2",
|
"nix 0.25.0",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
"wayland-scanner",
|
"wayland-scanner",
|
||||||
|
|
@ -2941,8 +2938,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-protocols"
|
name = "wayland-protocols"
|
||||||
version = "0.30.0-beta.9"
|
version = "0.30.0-beta.13"
|
||||||
source = "git+https://github.com/smithay/wayland-rs#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/smithay/wayland-rs#051cbf6e38f4532c74ab5fc9a8d39ed84e1f2e04"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
|
|
@ -2952,8 +2949,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-protocols-wlr"
|
name = "wayland-protocols-wlr"
|
||||||
version = "0.1.0-beta.9"
|
version = "0.1.0-beta.13"
|
||||||
source = "git+https://github.com/smithay/wayland-rs#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/smithay/wayland-rs#051cbf6e38f4532c74ab5fc9a8d39ed84e1f2e04"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
|
|
@ -2964,8 +2961,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-scanner"
|
name = "wayland-scanner"
|
||||||
version = "0.30.0-beta.9"
|
version = "0.30.0-beta.13"
|
||||||
source = "git+https://github.com/smithay/wayland-rs#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/smithay/wayland-rs#051cbf6e38f4532c74ab5fc9a8d39ed84e1f2e04"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quick-xml",
|
"quick-xml",
|
||||||
|
|
@ -2975,8 +2972,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-sys"
|
name = "wayland-sys"
|
||||||
version = "0.30.0-beta.9"
|
version = "0.30.0-beta.13"
|
||||||
source = "git+https://github.com/smithay/wayland-rs#fa4be85e8f3b57c8b6e8dd2476d6b4734b810e59"
|
source = "git+https://github.com/smithay/wayland-rs#051cbf6e38f4532c74ab5fc9a8d39ed84e1f2e04"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dlib",
|
"dlib",
|
||||||
"log",
|
"log",
|
||||||
|
|
|
||||||
14
Cargo.toml
14
Cargo.toml
|
|
@ -2,7 +2,6 @@
|
||||||
members = [
|
members = [
|
||||||
"applets/cosmic-applet-audio",
|
"applets/cosmic-applet-audio",
|
||||||
"applets/cosmic-applet-battery",
|
"applets/cosmic-applet-battery",
|
||||||
"applets/cosmic-applet-graphics",
|
|
||||||
"applets/cosmic-applet-network",
|
"applets/cosmic-applet-network",
|
||||||
"applets/cosmic-applet-notifications",
|
"applets/cosmic-applet-notifications",
|
||||||
"applets/cosmic-applet-power",
|
"applets/cosmic-applet-power",
|
||||||
|
|
@ -13,11 +12,14 @@ members = [
|
||||||
"applets/cosmic-panel-button",
|
"applets/cosmic-panel-button",
|
||||||
"libcosmic-applet",
|
"libcosmic-applet",
|
||||||
]
|
]
|
||||||
|
exclude = [
|
||||||
|
"applets/cosmic-applet-graphics",
|
||||||
|
]
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
wayland-protocols = { git = "https://github.com/smithay/wayland-rs", version = "0.30.0-beta.9"}
|
wayland-protocols = { git = "https://github.com/smithay/wayland-rs", version = "0.30.0-beta.13"}
|
||||||
wayland-protocols-wlr = { git = "https://github.com/smithay/wayland-rs", version = "0.1.0-beta.9"}
|
wayland-protocols-wlr = { git = "https://github.com/smithay/wayland-rs", version = "0.1.0-beta.9"}
|
||||||
wayland-sys = { git = "https://github.com/smithay/wayland-rs", version = "0.30.0-beta.9"}
|
wayland-sys = { git = "https://github.com/smithay/wayland-rs", version = "0.30.0-beta.13"}
|
||||||
wayland-backend = { git = "https://github.com/smithay/wayland-rs", version = "0.1.0-beta.9"}
|
wayland-backend = { git = "https://github.com/smithay/wayland-rs", version = "0.1.0-beta.13"}
|
||||||
wayland-scanner = { git = "https://github.com/smithay/wayland-rs", version = "0.30.0-beta.9"}
|
wayland-scanner = { git = "https://github.com/smithay/wayland-rs", version = "0.30.0-beta.13"}
|
||||||
wayland-client = { git = "https://github.com/smithay/wayland-rs", version = "0.30.0-beta.9"}
|
wayland-client = { git = "https://github.com/smithay/wayland-rs", version = "0.30.0-beta.13"}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! Utilities for using an [`EventQueue`] from wayland-client with an event loop that performs polling with
|
//! Utilities for using an [`EventQueue`] from wayland-client with an event loop that performs polling with
|
||||||
//! [`calloop`](https://crates.io/crates/calloop).
|
//! [`calloop`](https://crates.io/crates/calloop).
|
||||||
|
|
||||||
use std::{io, os::unix::prelude::RawFd};
|
use std::{io, os::unix::prelude::{RawFd, AsRawFd}};
|
||||||
|
|
||||||
use calloop::{
|
use calloop::{
|
||||||
generic::Generic, EventSource, InsertError, Interest, LoopHandle, Mode, Poll, PostAction,
|
generic::Generic, EventSource, InsertError, Interest, LoopHandle, Mode, Poll, PostAction,
|
||||||
|
|
@ -30,7 +30,7 @@ impl<D> WaylandSource<D> {
|
||||||
/// Wrap an [`EventQueue`] as a [`WaylandSource`].
|
/// Wrap an [`EventQueue`] as a [`WaylandSource`].
|
||||||
pub fn new(queue: EventQueue<D>) -> Result<WaylandSource<D>, WaylandError> {
|
pub fn new(queue: EventQueue<D>) -> Result<WaylandSource<D>, WaylandError> {
|
||||||
let guard = queue.prepare_read()?;
|
let guard = queue.prepare_read()?;
|
||||||
let fd = Generic::new(guard.connection_fd(), Interest::READ, Mode::Level);
|
let fd = Generic::new(guard.connection_fd().as_raw_fd(), Interest::READ, Mode::Level);
|
||||||
drop(guard);
|
drop(guard);
|
||||||
|
|
||||||
Ok(WaylandSource {
|
Ok(WaylandSource {
|
||||||
|
|
@ -192,12 +192,12 @@ impl<D> WaylandSource<D> {
|
||||||
break Err(Errno::EPROTO.into());
|
break Err(Errno::EPROTO.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(DispatchError::BadMessage { msg, interface }) => {
|
Err(DispatchError::BadMessage { sender_id, interface, opcode }) => {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Bad message on interface \"{}\": (opcode: {}, args: {:?})",
|
"Bad message on interface \"{}\": (opcode: {}, sender_id: {:?})",
|
||||||
interface,
|
interface,
|
||||||
msg.opcode,
|
opcode,
|
||||||
msg.args,
|
sender_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
break Err(Errno::EPROTO.into());
|
break Err(Errno::EPROTO.into());
|
||||||
|
|
|
||||||
3426
applets/cosmic-applet-graphics/Cargo.lock
generated
Normal file
3426
applets/cosmic-applet-graphics/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -6,11 +6,10 @@ 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]
|
||||||
gtk4 = { git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_2"] }
|
zbus = "3.4"
|
||||||
adw = { git = "https://gitlab.gnome.org/World/Rust/libadwaita-rs", package = "libadwaita"}
|
libcosmic = { git = "https://github.com/pop-os/libcosmic/", branch = "sctk-cosmic-design-system", default-features = false, features = ["wayland", "applet"] }
|
||||||
libcosmic = { git = "https://github.com/pop-os/libcosmic", default-features = false }
|
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", default-features = false }
|
||||||
libcosmic-applet = { path = "../../libcosmic-applet" }
|
iced_sctk = { git = "https://github.com/pop-os/iced-sctk" }
|
||||||
once_cell = "1.9.0"
|
# iced_sctk = { path = "../../../fork/iced-sctk" }
|
||||||
relm4-macros = { git = "https://github.com/Relm4/Relm4.git", branch = "next" }
|
sctk = { package = "smithay-client-toolkit", git = "https://github.com/Smithay/client-toolkit" }
|
||||||
tokio = { version = "1.16.1", features = ["full"] }
|
|
||||||
zbus = "2.1.1"
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
//! # DBus interface proxy for: `com.system76.PowerDaemon`
|
//! # DBus interface proxy for: `com.system76.PowerDaemon`
|
||||||
//!
|
//!
|
||||||
//! This code was generated by `zbus-xmlgen` `2.0.1` from DBus introspection data.
|
//! This code was generated by `zbus-xmlgen` `3.0.0` from DBus introspection data.
|
||||||
//! Source: `Interface '/com/system76/PowerDaemon' from service 'com.system76.PowerDaemon' on system bus`.
|
//! Source: `Interface '/com/system76/PowerDaemon' from service 'com.system76.PowerDaemon' on system bus`.
|
||||||
//!
|
//!
|
||||||
//! You may prefer to adapt it, instead of using it verbatim.
|
//! You may prefer to adapt it, instead of using it verbatim.
|
||||||
|
|
@ -18,11 +18,10 @@
|
||||||
//!
|
//!
|
||||||
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
|
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
|
||||||
|
|
||||||
use zbus::dbus_proxy;
|
use zbus::{dbus_proxy, Connection};
|
||||||
|
|
||||||
#[dbus_proxy(
|
#[dbus_proxy(
|
||||||
interface = "com.system76.PowerDaemon",
|
interface = "com.system76.PowerDaemon",
|
||||||
default_service = "com.system76.PowerDaemon",
|
|
||||||
default_path = "/com/system76/PowerDaemon"
|
default_path = "/com/system76/PowerDaemon"
|
||||||
)]
|
)]
|
||||||
trait PowerDaemon {
|
trait PowerDaemon {
|
||||||
|
|
@ -78,3 +77,17 @@ trait PowerDaemon {
|
||||||
#[dbus_proxy(signal)]
|
#[dbus_proxy(signal)]
|
||||||
fn power_profile_switch(&self, profile: &str) -> zbus::Result<()>;
|
fn power_profile_switch(&self, profile: &str) -> zbus::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn init() -> Option<(Connection, PowerDaemonProxy<'static>)> {
|
||||||
|
let conn = match Connection::system().await {
|
||||||
|
Ok(conn) => conn,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let proxy = match PowerDaemonProxy::new(&conn).await {
|
||||||
|
Ok(p) => p,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
Some((conn, proxy))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
use crate::dbus::PowerDaemonProxy;
|
use crate::dbus::PowerDaemonProxy;
|
||||||
use zbus::Result;
|
use zbus::Result;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||||
pub enum Graphics {
|
pub enum Graphics {
|
||||||
Integrated,
|
Integrated,
|
||||||
Hybrid,
|
Hybrid,
|
||||||
|
|
@ -10,7 +10,7 @@ pub enum Graphics {
|
||||||
Compute,
|
Compute,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_current_graphics(daemon: &PowerDaemonProxy<'_>) -> Result<Graphics> {
|
pub async fn get_current_graphics(daemon: PowerDaemonProxy<'_>) -> Result<Graphics> {
|
||||||
let graphics = daemon.get_graphics().await?;
|
let graphics = daemon.get_graphics().await?;
|
||||||
match graphics.as_str() {
|
match graphics.as_str() {
|
||||||
"integrated" => Ok(Graphics::Integrated),
|
"integrated" => Ok(Graphics::Integrated),
|
||||||
|
|
@ -21,7 +21,7 @@ pub async fn get_current_graphics(daemon: &PowerDaemonProxy<'_>) -> Result<Graph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_graphics(daemon: &PowerDaemonProxy<'_>, graphics: Graphics) -> Result<()> {
|
pub async fn set_graphics(daemon: PowerDaemonProxy<'_>, graphics: Graphics) -> Result<()> {
|
||||||
let graphics_str = match graphics {
|
let graphics_str = match graphics {
|
||||||
Graphics::Integrated => "integrated",
|
Graphics::Integrated => "integrated",
|
||||||
Graphics::Hybrid => "hybrid",
|
Graphics::Hybrid => "hybrid",
|
||||||
|
|
|
||||||
|
|
@ -1,178 +1,37 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
mod dbus;
|
||||||
|
mod graphics;
|
||||||
|
mod window;
|
||||||
|
|
||||||
#![allow(unused_parens, clippy::double_parens)] // needed for a quirk in the view! macro
|
use cosmic::{
|
||||||
|
iced::{sctk_settings::InitialSurface, Application},
|
||||||
#[macro_use]
|
iced_native::command::platform_specific::wayland::window::SctkWindowSettings,
|
||||||
extern crate relm4_macros;
|
iced_native::window::Settings,
|
||||||
|
settings,
|
||||||
pub mod dbus;
|
|
||||||
pub mod graphics;
|
|
||||||
pub mod mode_box;
|
|
||||||
|
|
||||||
use self::{dbus::PowerDaemonProxy, graphics::Graphics, mode_box::ModeSelection};
|
|
||||||
use gtk4::{
|
|
||||||
glib::{self, clone, MainContext, PRIORITY_DEFAULT},
|
|
||||||
prelude::*,
|
|
||||||
Align, Label, ListBox, ListBoxRow, Orientation, Overlay, Separator, Spinner,
|
|
||||||
};
|
};
|
||||||
use once_cell::sync::Lazy;
|
use cosmic_panel_config::PanelSize;
|
||||||
use tokio::runtime::Runtime;
|
use window::*;
|
||||||
|
|
||||||
static RT: Lazy<Runtime> = Lazy::new(|| Runtime::new().expect("failed to build tokio runtime"));
|
pub fn main() -> cosmic::iced::Result {
|
||||||
|
let mut settings = settings();
|
||||||
async fn get_current_graphics() -> zbus::Result<Graphics> {
|
let pixels = std::env::var("COSMIC_PANEL_SIZE")
|
||||||
let connection = zbus::Connection::system().await?;
|
.ok()
|
||||||
let proxy = PowerDaemonProxy::new(&connection).await?;
|
.and_then(|size| match size.parse::<PanelSize>() {
|
||||||
graphics::get_current_graphics(&proxy).await
|
Ok(PanelSize::XL) => Some(64),
|
||||||
}
|
Ok(PanelSize::L) => Some(48),
|
||||||
|
Ok(PanelSize::M) => Some(36),
|
||||||
async fn set_graphics(graphics_mode: Graphics) -> zbus::Result<()> {
|
Ok(PanelSize::S) => Some(24),
|
||||||
let connection = zbus::Connection::system().await?;
|
Ok(PanelSize::XS) => Some(18),
|
||||||
let proxy = PowerDaemonProxy::new(&connection).await?;
|
Err(_) => Some(36),
|
||||||
graphics::set_graphics(&proxy, graphics_mode).await
|
})
|
||||||
}
|
.unwrap_or(36);
|
||||||
|
settings.initial_surface = InitialSurface::XdgWindow(SctkWindowSettings {
|
||||||
fn row_clicked(_: &ListBox, row: &ListBoxRow) {
|
iced_settings: Settings {
|
||||||
let child = row.child().expect("UNEXPECTED: row has no child");
|
size: (pixels + 32, pixels + 16),
|
||||||
let selector = child
|
min_size: Some((pixels + 32, pixels + 16)),
|
||||||
.downcast::<ModeSelection>()
|
max_size: Some((pixels + 32, pixels + 16)),
|
||||||
.expect("UNEXPECTED: child is not a mode selector");
|
..Default::default()
|
||||||
selector.emit_activate();
|
},
|
||||||
}
|
..Default::default()
|
||||||
|
});
|
||||||
fn main() {
|
Window::run(settings)
|
||||||
let _monitors = libcosmic::init();
|
|
||||||
|
|
||||||
let provider = gtk4::CssProvider::new();
|
|
||||||
provider.load_from_data(include_bytes!("style.css"));
|
|
||||||
gtk4::StyleContext::add_provider_for_display(
|
|
||||||
>k4::gdk::Display::default().expect("Could not connect to a display."),
|
|
||||||
&provider,
|
|
||||||
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
|
|
||||||
);
|
|
||||||
|
|
||||||
let current_graphics = RT
|
|
||||||
.block_on(get_current_graphics())
|
|
||||||
.expect("failed to connect to system76-power");
|
|
||||||
|
|
||||||
let (tx, rx) = MainContext::channel::<bool>(PRIORITY_DEFAULT);
|
|
||||||
|
|
||||||
view! {
|
|
||||||
window = libcosmic_applet::AppletWindow {
|
|
||||||
set_title: Some("COSMIC Graphics Applet"),
|
|
||||||
#[wrap(Some)]
|
|
||||||
set_child = &libcosmic_applet::AppletButton {
|
|
||||||
set_button_icon_name: "input-gaming-symbolic",
|
|
||||||
#[wrap(Some)]
|
|
||||||
set_popover_child: main_overlay = &Overlay {
|
|
||||||
add_overlay: loading_box = >k4::Box {
|
|
||||||
append: loading_explain_box = >k4::Box {
|
|
||||||
set_orientation: Orientation::Vertical,
|
|
||||||
set_halign: Align::Center,
|
|
||||||
set_valign: Align::Center,
|
|
||||||
append: loading_spinner = &Spinner {
|
|
||||||
set_halign: Align::Center,
|
|
||||||
},
|
|
||||||
append: loading_explain = &Label {
|
|
||||||
set_label: "Please wait while your graphics mode is set...",
|
|
||||||
set_halign: Align::Center,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
set_halign: Align::Center,
|
|
||||||
set_valign: Align::Center,
|
|
||||||
set_hexpand: true,
|
|
||||||
set_vexpand: true,
|
|
||||||
set_visible: false,
|
|
||||||
add_css_class: "loading-overlay",
|
|
||||||
},
|
|
||||||
#[wrap(Some)]
|
|
||||||
set_child: main_box = >k4::Box {
|
|
||||||
set_orientation: Orientation::Vertical,
|
|
||||||
set_spacing: 10,
|
|
||||||
set_margin_top: 20,
|
|
||||||
set_margin_bottom: 20,
|
|
||||||
set_margin_start: 24,
|
|
||||||
set_margin_end: 24,
|
|
||||||
append: mode_label = &Label {
|
|
||||||
set_text: "Graphics Mode"
|
|
||||||
},
|
|
||||||
append: separator = &Separator {
|
|
||||||
set_orientation: Orientation::Horizontal
|
|
||||||
},
|
|
||||||
append: graphics_modes_list = &ListBox {
|
|
||||||
connect_row_activated: row_clicked,
|
|
||||||
append: integrated_selector = &ModeSelection {
|
|
||||||
set_title: "Integrated Graphics",
|
|
||||||
set_description: "Disables external displays. Requires Restart.",
|
|
||||||
set_active: (current_graphics == Graphics::Integrated),
|
|
||||||
connect_toggled: clone!(@strong tx => move |_| {
|
|
||||||
tx.send(true).expect("failed to send to main context");
|
|
||||||
let tx = tx.clone();
|
|
||||||
RT.spawn(async move {
|
|
||||||
set_graphics(Graphics::Integrated).await.expect("failed to set graphics mode");
|
|
||||||
tx.send(false).expect("failed to send to main context");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
|
||||||
append: nvidia_selector = &ModeSelection {
|
|
||||||
set_title: "NVIDIA Graphics",
|
|
||||||
set_group: Some(&integrated_selector),
|
|
||||||
set_active: (current_graphics == Graphics::Nvidia),
|
|
||||||
connect_toggled: clone!(@strong tx => move |_| {
|
|
||||||
tx.send(true).expect("failed to send to main context");
|
|
||||||
let tx = tx.clone();
|
|
||||||
RT.spawn(async move {
|
|
||||||
set_graphics(Graphics::Nvidia).await.expect("failed to set graphics mode");
|
|
||||||
tx.send(false).expect("failed to send to main context");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
|
||||||
append: hybrid_selector = &ModeSelection {
|
|
||||||
set_title: "Hybrid Graphics",
|
|
||||||
set_description: "Requires Restart.",
|
|
||||||
set_group: Some(&integrated_selector),
|
|
||||||
set_active: (current_graphics == Graphics::Hybrid),
|
|
||||||
connect_toggled: clone!(@strong tx => move |_| {
|
|
||||||
tx.send(true).expect("failed to send to main context");
|
|
||||||
let tx = tx.clone();
|
|
||||||
RT.spawn(async move {
|
|
||||||
set_graphics(Graphics::Hybrid).await.expect("failed to set graphics mode");
|
|
||||||
tx.send(false).expect("failed to send to main context");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
|
||||||
append: compute_selector = &ModeSelection {
|
|
||||||
set_title: "Compute Graphics",
|
|
||||||
set_description: "Disables external displays. Requires Restart.",
|
|
||||||
set_group: Some(&integrated_selector),
|
|
||||||
set_active: (current_graphics == Graphics::Compute),
|
|
||||||
connect_toggled: clone!(@strong tx => move |_| {
|
|
||||||
tx.send(true).expect("failed to send to main context");
|
|
||||||
let tx = tx.clone();
|
|
||||||
RT.spawn(async move {
|
|
||||||
set_graphics(Graphics::Compute).await.expect("failed to set graphics mode");
|
|
||||||
tx.send(false).expect("failed to send to main context");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rx.attach(
|
|
||||||
None,
|
|
||||||
clone!(@weak loading_box, @weak loading_spinner => @default-return Continue(true), move |val| {
|
|
||||||
loading_box.set_visible(val);
|
|
||||||
loading_spinner.set_spinning(val);
|
|
||||||
Continue(true)
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
window.show();
|
|
||||||
|
|
||||||
let main_loop = glib::MainLoop::new(None, false);
|
|
||||||
main_loop.run();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
use gtk4::{
|
|
||||||
glib::{self, Object},
|
|
||||||
prelude::*,
|
|
||||||
subclass::prelude::*,
|
|
||||||
Align, CheckButton, Label, Orientation,
|
|
||||||
};
|
|
||||||
|
|
||||||
glib::wrapper! {
|
|
||||||
pub struct ModeSelection(ObjectSubclass<ModeSelectionImp>)
|
|
||||||
@extends gtk4::Widget,
|
|
||||||
@implements gtk4::Accessible;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModeSelection {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_title(&self, title: &str) {
|
|
||||||
self.inner().label.set_text(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_description(&self, title: &str) {
|
|
||||||
let inner = self.inner();
|
|
||||||
inner.description.set_text(title);
|
|
||||||
inner.description.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_active(&self) -> bool {
|
|
||||||
self.inner().check.is_active()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_active(&self, setting: bool) {
|
|
||||||
self.inner().check.set_active(setting)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_group(&self, group: Option<&ModeSelection>) {
|
|
||||||
self.inner()
|
|
||||||
.check
|
|
||||||
.set_group(group.map(|x| &x.inner().check))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn connect_toggled<F: Fn(&CheckButton) + 'static>(&self, f: F) {
|
|
||||||
self.inner().check.connect_toggled(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn emit_activate(&self) {
|
|
||||||
self.inner().check.emit_activate();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inner(&self) -> &ModeSelectionImp {
|
|
||||||
ModeSelectionImp::from_instance(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ModeSelection {
|
|
||||||
fn default() -> Self {
|
|
||||||
Object::new(&[]).expect("Failed to create `ModeSelection`.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct ModeSelectionImp {
|
|
||||||
inner_box: gtk4::Box,
|
|
||||||
label_box: gtk4::Box,
|
|
||||||
label: Label,
|
|
||||||
description: Label,
|
|
||||||
check: CheckButton,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[glib::object_subclass]
|
|
||||||
impl ObjectSubclass for ModeSelectionImp {
|
|
||||||
const NAME: &'static str = "ModeSelection";
|
|
||||||
type Type = ModeSelection;
|
|
||||||
type ParentType = gtk4::Widget;
|
|
||||||
|
|
||||||
fn class_init(klass: &mut Self::Class) {
|
|
||||||
klass.set_layout_manager_type::<gtk4::BinLayout>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ObjectImpl for ModeSelectionImp {
|
|
||||||
fn constructed(&self, obj: &Self::Type) {
|
|
||||||
self.parent_constructed(obj);
|
|
||||||
|
|
||||||
self.check.set_halign(Align::End);
|
|
||||||
|
|
||||||
self.label.set_halign(Align::Start);
|
|
||||||
self.label.add_css_class("title");
|
|
||||||
|
|
||||||
self.description.set_halign(Align::Start);
|
|
||||||
self.description.add_css_class("description");
|
|
||||||
self.description.hide();
|
|
||||||
|
|
||||||
self.label_box.set_orientation(Orientation::Vertical);
|
|
||||||
self.label_box.set_hexpand(true);
|
|
||||||
self.label_box.append(&self.label);
|
|
||||||
self.label_box.append(&self.description);
|
|
||||||
|
|
||||||
self.inner_box.set_orientation(Orientation::Horizontal);
|
|
||||||
self.inner_box.append(&self.label_box);
|
|
||||||
self.inner_box.append(&self.check);
|
|
||||||
self.inner_box.set_parent(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dispose(&self, _obj: &Self::Type) {
|
|
||||||
self.inner_box.remove(&self.label);
|
|
||||||
self.inner_box.remove(&self.check);
|
|
||||||
self.inner_box.unparent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WidgetImpl for ModeSelectionImp {}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
.loading-overlay {
|
|
||||||
background-color: #2f2f2f;
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
|
||||||
287
applets/cosmic-applet-graphics/src/window.rs
Normal file
287
applets/cosmic-applet-graphics/src/window.rs
Normal file
|
|
@ -0,0 +1,287 @@
|
||||||
|
use crate::dbus::{self, PowerDaemonProxy};
|
||||||
|
use crate::graphics::{get_current_graphics, set_graphics, Graphics};
|
||||||
|
use cosmic::applet::{get_popup_settings, icon_button, popup_container};
|
||||||
|
use cosmic::iced_style::application::{self, Appearance};
|
||||||
|
use cosmic::separator;
|
||||||
|
use cosmic::{
|
||||||
|
iced::widget::{column, radio, text},
|
||||||
|
iced::{self, Application, Command, Length},
|
||||||
|
iced_native::window,
|
||||||
|
theme::{self, Theme},
|
||||||
|
Element,
|
||||||
|
};
|
||||||
|
use cosmic_panel_config::{PanelAnchor, PanelSize};
|
||||||
|
use iced_sctk::alignment::Horizontal;
|
||||||
|
use iced_sctk::application::SurfaceIdWrapper;
|
||||||
|
use iced_sctk::commands::popup::{destroy_popup, get_popup};
|
||||||
|
use iced_sctk::Color;
|
||||||
|
use zbus::Connection;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum State {
|
||||||
|
SelectGraphicsMode(bool),
|
||||||
|
SettingGraphicsMode(Graphics),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum GraphicsMode {
|
||||||
|
SelectedGraphicsMode(Graphics),
|
||||||
|
CurrentGraphicsMode(Graphics),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GraphicsMode {
|
||||||
|
fn inner(&self) -> Graphics {
|
||||||
|
match self {
|
||||||
|
GraphicsMode::SelectedGraphicsMode(g) => *g,
|
||||||
|
GraphicsMode::CurrentGraphicsMode(g) => *g,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for State {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::SelectGraphicsMode(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Window {
|
||||||
|
popup: Option<window::Id>,
|
||||||
|
graphics_mode: Option<GraphicsMode>,
|
||||||
|
id_ctr: u32,
|
||||||
|
icon_size: u16,
|
||||||
|
anchor: PanelAnchor,
|
||||||
|
theme: Theme,
|
||||||
|
dbus: Option<(Connection, PowerDaemonProxy<'static>)>,
|
||||||
|
state: State,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Message {
|
||||||
|
CurrentGraphics(Option<Graphics>),
|
||||||
|
SelectedGraphicsMode(Option<Graphics>),
|
||||||
|
DBusInit(Option<(Connection, PowerDaemonProxy<'static>)>),
|
||||||
|
SelectGraphicsMode(Graphics),
|
||||||
|
TogglePopup,
|
||||||
|
PopupClosed(window::Id),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Application for Window {
|
||||||
|
type Executor = iced::executor::Default;
|
||||||
|
type Flags = ();
|
||||||
|
type Message = Message;
|
||||||
|
type Theme = Theme;
|
||||||
|
|
||||||
|
fn new(_flags: ()) -> (Self, Command<Self::Message>) {
|
||||||
|
let mut window = Window::default();
|
||||||
|
let pixels = std::env::var("COSMIC_PANEL_SIZE")
|
||||||
|
.ok()
|
||||||
|
.and_then(|size| match size.parse::<PanelSize>() {
|
||||||
|
Ok(PanelSize::XL) => Some(64),
|
||||||
|
Ok(PanelSize::L) => Some(36),
|
||||||
|
Ok(PanelSize::M) => Some(24),
|
||||||
|
Ok(PanelSize::S) => Some(16),
|
||||||
|
Ok(PanelSize::XS) => Some(12),
|
||||||
|
Err(_) => Some(12),
|
||||||
|
})
|
||||||
|
.unwrap_or(16);
|
||||||
|
window.icon_size = pixels;
|
||||||
|
window.anchor = std::env::var("COSMIC_PANEL_ANCHOR")
|
||||||
|
.ok()
|
||||||
|
.map(|size| match size.parse::<PanelAnchor>() {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(_) => PanelAnchor::Top,
|
||||||
|
})
|
||||||
|
.unwrap_or(PanelAnchor::Top);
|
||||||
|
(
|
||||||
|
window,
|
||||||
|
Command::perform(dbus::init(), |dbus_init| Message::DBusInit(dbus_init)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&self) -> String {
|
||||||
|
String::from("Cosmic Graphics Applet")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, message: Message) -> iced::Command<Self::Message> {
|
||||||
|
match message {
|
||||||
|
Message::SelectGraphicsMode(new_graphics_mode) => {
|
||||||
|
if let Some((_, proxy)) = self.dbus.as_ref() {
|
||||||
|
self.state = State::SettingGraphicsMode(new_graphics_mode);
|
||||||
|
return Command::perform(
|
||||||
|
set_graphics(proxy.clone(), new_graphics_mode),
|
||||||
|
move |success| {
|
||||||
|
Message::SelectedGraphicsMode(success.ok().map(|_| new_graphics_mode))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::SelectedGraphicsMode(g) => {
|
||||||
|
if let Some(g) = g {
|
||||||
|
self.graphics_mode
|
||||||
|
.replace(GraphicsMode::SelectedGraphicsMode(g));
|
||||||
|
self.state = State::SelectGraphicsMode(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::TogglePopup => {
|
||||||
|
if let Some(p) = self.popup.take() {
|
||||||
|
return destroy_popup(p);
|
||||||
|
} else {
|
||||||
|
self.id_ctr += 1;
|
||||||
|
let new_id = window::Id::new(self.id_ctr);
|
||||||
|
self.popup.replace(new_id);
|
||||||
|
let mut commands = Vec::new();
|
||||||
|
if let Some((_, proxy)) = self.dbus.as_ref() {
|
||||||
|
commands.push(Command::perform(
|
||||||
|
get_current_graphics(proxy.clone()),
|
||||||
|
|cur_graphics| Message::CurrentGraphics(cur_graphics.ok()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let popup_settings =
|
||||||
|
get_popup_settings(window::Id::new(0), new_id, (200, 240), None, None);
|
||||||
|
commands.push(get_popup(popup_settings));
|
||||||
|
return Command::batch(commands);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::DBusInit(dbus) => {
|
||||||
|
self.dbus = dbus;
|
||||||
|
return Command::perform(
|
||||||
|
get_current_graphics(self.dbus.as_ref().unwrap().1.clone()),
|
||||||
|
|cur_graphics| {
|
||||||
|
Message::CurrentGraphics(match cur_graphics {
|
||||||
|
Ok(g) => Some(g),
|
||||||
|
Err(err) => {
|
||||||
|
dbg!(err);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Message::CurrentGraphics(g) => {
|
||||||
|
if let Some(g) = g {
|
||||||
|
self.graphics_mode = Some(match self.graphics_mode.take() {
|
||||||
|
Some(GraphicsMode::CurrentGraphicsMode(_)) | None => {
|
||||||
|
GraphicsMode::CurrentGraphicsMode(g)
|
||||||
|
}
|
||||||
|
Some(g) => g,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::PopupClosed(id) => {
|
||||||
|
if self.popup.as_ref() == Some(&id) {
|
||||||
|
self.popup = None;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Command::none()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self, id: SurfaceIdWrapper) -> Element<Message> {
|
||||||
|
match id {
|
||||||
|
SurfaceIdWrapper::LayerSurface(_) => unimplemented!(),
|
||||||
|
SurfaceIdWrapper::Window(_) => icon_button().on_press(Message::TogglePopup).into(),
|
||||||
|
SurfaceIdWrapper::Popup(_) => {
|
||||||
|
let content = match self.state {
|
||||||
|
State::SelectGraphicsMode(pending_restart) => {
|
||||||
|
let mut content_list = vec![
|
||||||
|
radio(
|
||||||
|
"Integrated Graphics",
|
||||||
|
Graphics::Integrated,
|
||||||
|
self.graphics_mode.map(|g| g.inner()),
|
||||||
|
|g| Message::SelectGraphicsMode(g),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
radio(
|
||||||
|
"Nvidia Graphics",
|
||||||
|
Graphics::Nvidia,
|
||||||
|
self.graphics_mode.map(|g| g.inner()),
|
||||||
|
|g| Message::SelectGraphicsMode(g),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
radio(
|
||||||
|
"Hybrid Graphics",
|
||||||
|
Graphics::Hybrid,
|
||||||
|
self.graphics_mode.map(|g| g.inner()),
|
||||||
|
|g| Message::SelectGraphicsMode(g),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
radio(
|
||||||
|
"Compute Graphics",
|
||||||
|
Graphics::Compute,
|
||||||
|
self.graphics_mode.map(|g| g.inner()),
|
||||||
|
|g| Message::SelectGraphicsMode(g),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
];
|
||||||
|
if pending_restart {
|
||||||
|
content_list.insert(
|
||||||
|
0,
|
||||||
|
text("Restart to apply changes")
|
||||||
|
.width(Length::Fill)
|
||||||
|
.horizontal_alignment(Horizontal::Center)
|
||||||
|
.size(16)
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
column(content_list).padding([8, 0]).spacing(8).into()
|
||||||
|
}
|
||||||
|
State::SettingGraphicsMode(graphics) => {
|
||||||
|
let graphics_str = match graphics {
|
||||||
|
Graphics::Integrated => "integrated",
|
||||||
|
Graphics::Hybrid => "hybrid",
|
||||||
|
Graphics::Nvidia => "nvidia",
|
||||||
|
Graphics::Compute => "compute",
|
||||||
|
};
|
||||||
|
column(vec![text(format!(
|
||||||
|
"Setting graphics mode to {graphics_str}..."
|
||||||
|
))
|
||||||
|
.width(Length::Fill)
|
||||||
|
.horizontal_alignment(Horizontal::Center)
|
||||||
|
.into()])
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
popup_container(
|
||||||
|
column(vec![
|
||||||
|
text("Graphics Mode")
|
||||||
|
.width(Length::Fill)
|
||||||
|
.horizontal_alignment(Horizontal::Center)
|
||||||
|
.size(24)
|
||||||
|
.into(),
|
||||||
|
separator!(1).into(),
|
||||||
|
content,
|
||||||
|
])
|
||||||
|
.padding(4)
|
||||||
|
.spacing(4),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close_requested(&self, id: SurfaceIdWrapper) -> Self::Message {
|
||||||
|
match id {
|
||||||
|
SurfaceIdWrapper::LayerSurface(_) | SurfaceIdWrapper::Window(_) => unimplemented!(),
|
||||||
|
SurfaceIdWrapper::Popup(id) => {
|
||||||
|
Message::PopupClosed(id)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self) -> <Self::Theme as application::StyleSheet>::Style {
|
||||||
|
<Self::Theme as application::StyleSheet>::Style::Custom(|theme| Appearance {
|
||||||
|
background_color: Color::from_rgba(0.0, 0.0, 0.0, 0.0),
|
||||||
|
text_color: theme.cosmic().on_bg_color().into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_exit(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn theme(&self) -> Theme {
|
||||||
|
self.theme
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
//! Utilities for using an [`EventQueue`] from wayland-client with an event loop that performs polling with
|
//! Utilities for using an [`EventQueue`] from wayland-client with an event loop that performs polling with
|
||||||
//! [`calloop`](https://crates.io/crates/calloop).
|
//! [`calloop`](https://crates.io/crates/calloop).
|
||||||
|
|
||||||
use std::{io, os::unix::prelude::RawFd};
|
use std::{io, os::unix::prelude::{RawFd, AsRawFd}};
|
||||||
|
|
||||||
use calloop::{
|
use calloop::{
|
||||||
generic::Generic, EventSource, InsertError, Interest, LoopHandle, Mode, Poll, PostAction,
|
generic::Generic, EventSource, InsertError, Interest, LoopHandle, Mode, Poll, PostAction,
|
||||||
|
|
@ -30,7 +30,7 @@ impl<D> WaylandSource<D> {
|
||||||
/// Wrap an [`EventQueue`] as a [`WaylandSource`].
|
/// Wrap an [`EventQueue`] as a [`WaylandSource`].
|
||||||
pub fn new(queue: EventQueue<D>) -> Result<WaylandSource<D>, WaylandError> {
|
pub fn new(queue: EventQueue<D>) -> Result<WaylandSource<D>, WaylandError> {
|
||||||
let guard = queue.prepare_read()?;
|
let guard = queue.prepare_read()?;
|
||||||
let fd = Generic::new(guard.connection_fd(), Interest::READ, Mode::Level);
|
let fd = Generic::new(guard.connection_fd().as_raw_fd(), Interest::READ, Mode::Level);
|
||||||
drop(guard);
|
drop(guard);
|
||||||
|
|
||||||
Ok(WaylandSource {
|
Ok(WaylandSource {
|
||||||
|
|
@ -192,12 +192,12 @@ impl<D> WaylandSource<D> {
|
||||||
break Err(Errno::EPROTO.into());
|
break Err(Errno::EPROTO.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(DispatchError::BadMessage { msg, interface }) => {
|
Err(DispatchError::BadMessage { sender_id, interface, opcode }) => {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Bad message on interface \"{}\": (opcode: {}, args: {:?})",
|
"Bad message on interface \"{}\": (opcode: {}, sender_id: {:?})",
|
||||||
interface,
|
interface,
|
||||||
msg.opcode,
|
opcode,
|
||||||
msg.args,
|
sender_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
break Err(Errno::EPROTO.into());
|
break Err(Errno::EPROTO.into());
|
||||||
|
|
|
||||||
7
debian/rules
vendored
7
debian/rules
vendored
|
|
@ -13,6 +13,7 @@ override_dh_shlibdeps:
|
||||||
override_dh_auto_clean:
|
override_dh_auto_clean:
|
||||||
if test "${CLEAN}" = "1"; then \
|
if test "${CLEAN}" = "1"; then \
|
||||||
cargo clean; \
|
cargo clean; \
|
||||||
|
cargo clean --manifest-path applets/cosmic-applet-graphics/Cargo.toml; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! ischroot && test "${VENDOR}" = "1"; then \
|
if ! ischroot && test "${VENDOR}" = "1"; then \
|
||||||
|
|
@ -21,6 +22,12 @@ override_dh_auto_clean:
|
||||||
echo 'directory = "vendor"' >> .cargo/config; \
|
echo 'directory = "vendor"' >> .cargo/config; \
|
||||||
tar pcf vendor.tar vendor; \
|
tar pcf vendor.tar vendor; \
|
||||||
rm -rf vendor; \
|
rm -rf vendor; \
|
||||||
|
cd applets/cosmic-applet-graphics/; \
|
||||||
|
mkdir -p .cargo; \
|
||||||
|
cargo vendor --sync Cargo.toml | head -n -1 > .cargo/config; \
|
||||||
|
echo 'directory = "vendor"' >> .cargo/config; \
|
||||||
|
tar pcf vendor.tar vendor; \
|
||||||
|
rm -rf vendor; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
override_dh_auto_build:
|
override_dh_auto_build:
|
||||||
|
|
|
||||||
17
justfile
17
justfile
|
|
@ -27,6 +27,10 @@ app_button_id := 'com.system76.CosmicPanelAppButton'
|
||||||
workspaces_button_id := 'com.system76.CosmicPanelWorkspacesButton'
|
workspaces_button_id := 'com.system76.CosmicPanelWorkspacesButton'
|
||||||
|
|
||||||
all: _extract_vendor
|
all: _extract_vendor
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
pushd applets/cosmic-applet-graphics/
|
||||||
|
cargo build {{cargo_args}}
|
||||||
|
popd
|
||||||
cargo build {{cargo_args}}
|
cargo build {{cargo_args}}
|
||||||
|
|
||||||
# Installs files into the system
|
# Installs files into the system
|
||||||
|
|
@ -47,12 +51,6 @@ install:
|
||||||
install -Dm0644 applets/cosmic-applet-battery/data/icons/{{battery_id}}.svg {{iconsdir}}/{{battery_id}}.svg
|
install -Dm0644 applets/cosmic-applet-battery/data/icons/{{battery_id}}.svg {{iconsdir}}/{{battery_id}}.svg
|
||||||
install -Dm0644 applets/cosmic-applet-battery/data/{{battery_id}}.desktop {{sharedir}}/applications/{{battery_id}}.desktop
|
install -Dm0644 applets/cosmic-applet-battery/data/{{battery_id}}.desktop {{sharedir}}/applications/{{battery_id}}.desktop
|
||||||
install -Dm0755 target/release/cosmic-applet-battery {{bindir}}/cosmic-applet-battery
|
install -Dm0755 target/release/cosmic-applet-battery {{bindir}}/cosmic-applet-battery
|
||||||
|
|
||||||
# graphics
|
|
||||||
install -Dm0644 applets/cosmic-applet-graphics/data/icons/{{graphics_id}}.svg {{iconsdir}}/{{graphics_id}}.svg
|
|
||||||
install -Dm0644 applets/cosmic-applet-graphics/data/{{graphics_id}}.desktop {{sharedir}}/applications/{{graphics_id}}.desktop
|
|
||||||
install -Dm0755 target/release/cosmic-applet-graphics {{bindir}}/cosmic-applet-graphics
|
|
||||||
|
|
||||||
# network
|
# network
|
||||||
install -Dm0644 applets/cosmic-applet-network/data/icons/{{network_id}}.svg {{iconsdir}}/{{network_id}}.svg
|
install -Dm0644 applets/cosmic-applet-network/data/icons/{{network_id}}.svg {{iconsdir}}/{{network_id}}.svg
|
||||||
install -Dm0644 applets/cosmic-applet-network/data/{{network_id}}.desktop {{sharedir}}/applications/{{network_id}}.desktop
|
install -Dm0644 applets/cosmic-applet-network/data/{{network_id}}.desktop {{sharedir}}/applications/{{network_id}}.desktop
|
||||||
|
|
@ -94,9 +92,16 @@ install:
|
||||||
# panel button
|
# panel button
|
||||||
install -Dm0755 target/release/cosmic-panel-button {{bindir}}/cosmic-panel-button
|
install -Dm0755 target/release/cosmic-panel-button {{bindir}}/cosmic-panel-button
|
||||||
|
|
||||||
|
# graphics
|
||||||
|
install -Dm0644 applets/cosmic-applet-graphics/data/icons/{{graphics_id}}.svg {{iconsdir}}/{{graphics_id}}.svg
|
||||||
|
install -Dm0644 applets/cosmic-applet-graphics/data/{{graphics_id}}.desktop {{sharedir}}/applications/{{graphics_id}}.desktop
|
||||||
|
install -Dm0755 applets/cosmic-applet-graphics/target/release/cosmic-applet-graphics {{bindir}}/cosmic-applet-graphics
|
||||||
|
|
||||||
|
|
||||||
# Extracts vendored dependencies if vendor=1
|
# Extracts vendored dependencies if vendor=1
|
||||||
_extract_vendor:
|
_extract_vendor:
|
||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
if test {{vendor}} = 1; then
|
if test {{vendor}} = 1; then
|
||||||
rm -rf vendor; tar pxf vendor.tar
|
rm -rf vendor; tar pxf vendor.tar
|
||||||
|
rm -rf applets/cosmic-applet-graphics/vendor; tar xf applets/cosmic-applet-graphics/vendor.tar --directory applets/cosmic-applet-graphics
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
1.63
|
1.65
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue