merge master_jammy and udpate to use latest cosmic panel config

This commit is contained in:
Ashley Wulber 2022-07-06 12:41:49 -04:00
commit 488fe6f186
No known key found for this signature in database
GPG key ID: 5216D4F46A90A820
32 changed files with 616 additions and 1057 deletions

342
Cargo.lock generated
View file

@ -17,27 +17,6 @@ version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
[[package]]
name = "appendlist"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e149dc73cd30538307e7ffa2acd3d2221148eaeed4871f246657b1c3eaa1cbd2"
[[package]]
name = "approx"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278"
dependencies = [
"num-traits",
]
[[package]]
name = "arc-swap"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f"
[[package]]
name = "async-broadcast"
version = "0.4.0"
@ -271,16 +250,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cgmath"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317"
dependencies = [
"approx",
"num-traits",
]
[[package]]
name = "chrono"
version = "0.4.19"
@ -366,8 +335,8 @@ dependencies = [
name = "cosmic-applet-graphics"
version = "0.1.0"
dependencies = [
"cosmic-panel-config",
"gtk4",
"libcosmic-applet",
"once_cell",
"relm4-macros",
"tokio",
@ -379,10 +348,10 @@ name = "cosmic-applet-network"
version = "0.1.0"
dependencies = [
"cosmic-dbus-networkmanager",
"cosmic-panel-config",
"futures-util",
"gtk4",
"itertools",
"libcosmic-applet",
"libcosmic-widgets",
"once_cell",
"relm4-macros",
@ -396,11 +365,11 @@ name = "cosmic-applet-notifications"
version = "0.1.0"
dependencies = [
"cascade",
"cosmic-panel-config",
"futures",
"gtk4",
"libcosmic-applet",
"once_cell",
"relm4-macros",
"serde",
"zbus",
"zbus_names",
@ -427,9 +396,9 @@ name = "cosmic-applet-status-area"
version = "0.1.0"
dependencies = [
"cascade",
"cosmic-panel-config",
"futures",
"gtk4",
"libcosmic-applet",
"once_cell",
"serde",
"zbus",
@ -443,9 +412,9 @@ version = "0.1.0"
dependencies = [
"cascade",
"chrono",
"cosmic-panel-config",
"futures",
"gtk4",
"libcosmic-applet",
"once_cell",
"serde",
"zbus",
@ -509,16 +478,16 @@ dependencies = [
[[package]]
name = "cosmic-panel-config"
version = "0.1.0"
source = "git+https://github.com/pop-os/cosmic-panel?branch=rework_0.30#b5834088e8e4ef097830d27eb03925dc78262d37"
source = "git+https://github.com/pop-os/cosmic-panel#791937b3515534f4df9bb47c1a6bd5189ff00644"
dependencies = [
"anyhow",
"gtk4",
"ron",
"serde",
"slog",
"smithay-client-toolkit",
"wayland-protocols",
"xdg",
"xdg-shell-wrapper",
"xdg-shell-wrapper-config",
]
[[package]]
@ -672,43 +641,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "drm"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "408e87132bd0d8a13a3b418b9d51fb92973b764d1d40785947d233ab2945fd27"
dependencies = [
"bitflags",
"drm-ffi",
"drm-fourcc",
"nix 0.22.3",
]
[[package]]
name = "drm-ffi"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "198d1b7fdb33b75e9bd08ba6842ddb730760f7eeea25552acc88c5403c4f0652"
dependencies = [
"drm-sys",
"nix 0.22.3",
]
[[package]]
name = "drm-fourcc"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4"
[[package]]
name = "drm-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5f45fcdd3b2f3c13fadea11b2a4eda2023e7de55021da039eac4a3beecfe91c"
dependencies = [
"libc",
]
[[package]]
name = "easy-parallel"
version = "3.2.0"
@ -1159,17 +1091,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "gl_generator"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
dependencies = [
"khronos_api",
"log",
"xml-rs",
]
[[package]]
name = "glib"
version = "0.15.12"
@ -1500,16 +1421,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indexmap"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -1563,12 +1474,6 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "khronos_api"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -1735,15 +1640,6 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memmap2"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357"
dependencies = [
"libc",
]
[[package]]
name = "memoffset"
version = "0.6.5"
@ -1753,12 +1649,6 @@ dependencies = [
"autocfg",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "mio"
version = "0.8.4"
@ -1830,16 +1720,6 @@ dependencies = [
"memoffset",
]
[[package]]
name = "nom"
version = "7.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-derive"
version = "0.3.3"
@ -2225,9 +2105,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.5.6"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
@ -2236,14 +2116,14 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.6.26"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "relm4"
version = "0.5.0-beta.1"
source = "git+https://github.com/relm4/relm4?branch=next#2caad49d8a554c8ecf20d2bc3bf13827ff5c2b46"
source = "git+https://github.com/relm4/relm4?branch=next#746d244004e23764294b23519f6f8be1002c1ceb"
dependencies = [
"async-broadcast",
"async-oneshot",
@ -2254,12 +2134,13 @@ dependencies = [
"once_cell",
"relm4-macros",
"tokio",
"tracing",
]
[[package]]
name = "relm4-macros"
version = "0.5.0-beta.1"
source = "git+https://github.com/relm4/relm4?branch=next#2caad49d8a554c8ecf20d2bc3bf13827ff5c2b46"
source = "git+https://github.com/relm4/relm4?branch=next#746d244004e23764294b23519f6f8be1002c1ceb"
dependencies = [
"proc-macro2",
"quote",
@ -2350,12 +2231,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scan_fmt"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248"
[[package]]
name = "scoped-tls"
version = "1.0.0"
@ -2462,12 +2337,6 @@ dependencies = [
"opaque-debug",
]
[[package]]
name = "shlex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
@ -2489,28 +2358,6 @@ version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06"
[[package]]
name = "slog-scope"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f95a4b4c3274cd2869549da82b57ccc930859bdbf5bcea0424bc5f140b3c786"
dependencies = [
"arc-swap",
"lazy_static",
"slog",
]
[[package]]
name = "slog-stdlog"
version = "4.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6706b2ace5bbae7291d3f8d2473e2bfab073ccd7d03670946197aec98471fa3e"
dependencies = [
"log",
"slog",
"slog-scope",
]
[[package]]
name = "slotmap"
version = "1.0.6"
@ -2526,58 +2373,6 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
[[package]]
name = "smithay"
version = "0.3.0"
source = "git+https://github.com/smithay/smithay?branch=fix/egl_zero_sized_buffers#bb79a79a6cf8246d857f30e3f2ceee35ab058238"
dependencies = [
"appendlist",
"bitflags",
"calloop",
"cgmath",
"downcast-rs",
"drm",
"drm-ffi",
"drm-fourcc",
"gl_generator",
"indexmap",
"lazy_static",
"libc",
"libloading",
"nix 0.22.3",
"once_cell",
"rand",
"scan_fmt",
"slog",
"slog-stdlog",
"tempfile",
"thiserror",
"wayland-backend",
"wayland-protocols 0.30.0-beta.5",
"wayland-protocols-wlr",
"wayland-server",
"wayland-sys 0.30.0-beta.5",
"xkbcommon",
]
[[package]]
name = "smithay-client-toolkit"
version = "0.15.4"
source = "git+https://github.com/wash2/client-toolkit.git#ebcf9b3ed6454b050621e021f4bf4136fc810965"
dependencies = [
"bitflags",
"calloop",
"dlib",
"lazy_static",
"log",
"memmap2",
"nix 0.22.3",
"pkg-config",
"wayland-client 0.29.4",
"wayland-cursor",
"wayland-protocols 0.29.4",
]
[[package]]
name = "socket2"
version = "0.4.4"
@ -2756,6 +2551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
dependencies = [
"cfg-if",
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@ -2970,7 +2766,7 @@ dependencies = [
"nix 0.24.1",
"scoped-tls",
"smallvec",
"wayland-sys 0.30.0-beta.5",
"wayland-sys 0.30.0-beta.7",
]
[[package]]
@ -2983,7 +2779,6 @@ dependencies = [
"downcast-rs",
"libc",
"nix 0.22.3",
"scoped-tls",
"wayland-commons",
"wayland-scanner 0.29.4",
"wayland-sys 0.29.4",
@ -3017,27 +2812,6 @@ dependencies = [
"wayland-sys 0.29.4",
]
[[package]]
name = "wayland-cursor"
version = "0.29.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd"
dependencies = [
"nix 0.22.3",
"wayland-client 0.29.4",
"xcursor",
]
[[package]]
name = "wayland-egl"
version = "0.29.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83281d69ee162b59031c666385e93bde4039ec553b90c4191cdb128ceea29a3a"
dependencies = [
"wayland-client 0.29.4",
"wayland-sys 0.29.4",
]
[[package]]
name = "wayland-protocols"
version = "0.29.4"
@ -3050,31 +2824,6 @@ dependencies = [
"wayland-scanner 0.29.4",
]
[[package]]
name = "wayland-protocols"
version = "0.30.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9f0d8437907ef09d984290034c4ae387e25a20da7b58be49537afa054fe9a8"
dependencies = [
"bitflags",
"wayland-backend",
"wayland-scanner 0.30.0-beta.5",
"wayland-server",
]
[[package]]
name = "wayland-protocols-wlr"
version = "0.1.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2c177888ec1668c25de67acbb87575efec1f071ed39322e74bbb4849649cd5b"
dependencies = [
"bitflags",
"wayland-backend",
"wayland-protocols 0.30.0-beta.5",
"wayland-scanner 0.30.0-beta.5",
"wayland-server",
]
[[package]]
name = "wayland-scanner"
version = "0.29.4"
@ -3098,41 +2847,23 @@ dependencies = [
"xml-rs",
]
[[package]]
name = "wayland-server"
version = "0.30.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13891361d1a0f6b85ca5f95d7fac6f7e2070d28c7442430082a63c40ae53d70e"
dependencies = [
"bitflags",
"downcast-rs",
"log",
"nix 0.24.1",
"thiserror",
"wayland-backend",
"wayland-scanner 0.30.0-beta.5",
]
[[package]]
name = "wayland-sys"
version = "0.29.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9341df79a8975679188e37dab3889bfa57c44ac2cb6da166f519a81cbe452d4"
dependencies = [
"dlib",
"pkg-config",
]
[[package]]
name = "wayland-sys"
version = "0.30.0-beta.5"
version = "0.30.0-beta.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3789e5a2e1c61b83b7a382f52ff8651d0a6544074e6012d4721f8e22335247de"
checksum = "f62b62672d36b6cf2f7d936f95c9f5894c0609190fa789c2ce46b73912baf239"
dependencies = [
"dlib",
"libc",
"log",
"memoffset",
"pkg-config",
]
@ -3229,15 +2960,6 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "xcursor"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7"
dependencies = [
"nom",
]
[[package]]
name = "xdg"
version = "2.4.1"
@ -3248,32 +2970,12 @@ dependencies = [
]
[[package]]
name = "xdg-shell-wrapper"
name = "xdg-shell-wrapper-config"
version = "0.1.0"
source = "git+https://github.com/pop-os/xdg-shell-wrapper?branch=rework-0.30#9b26291502c5e6d3b969e22f4b80fc57c0e3a6f4"
source = "git+https://github.com/pop-os/xdg-shell-wrapper#e523530fd900ae1985e664cce84c4066b23afea1"
dependencies = [
"anyhow",
"calloop",
"itertools",
"libc",
"once_cell",
"ron",
"serde",
"shlex",
"slog",
"smithay",
"smithay-client-toolkit",
"tempfile",
"wayland-egl",
]
[[package]]
name = "xkbcommon"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fda0ea5f7ddabd51deeeda7799bee06274112f577da7dd3d954b8eda731b2fce"
dependencies = [
"libc",
"wayland-protocols",
]
[[package]]

View file

@ -5,7 +5,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"], branch = "rework_0.30"}
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"] }
cascade = "1.0.0"
gtk4 = { git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_4"] }
gio = { git = "https://github.com/gtk-rs/gtk-rs-core" }

View file

@ -76,90 +76,93 @@ fn app(application: &Application) {
});
pa.connect().unwrap(); // XXX unwrap
view! {
window = libcosmic_applet::Applet {
window = libcosmic_applet::AppletWindow {
set_application: Some(application),
set_title: Some("COSMIC Network Applet"),
// TODO: adjust based on volume, mute
set_button_icon_name: "multimedia-volume-control-symbolic",
#[wrap(Some)]
set_popover_child: window_box = &GtkBox {
set_orientation: Orientation::Vertical,
set_spacing: 24,
append: output_box = &GtkBox {
set_orientation: Orientation::Horizontal,
set_spacing: 16,
append: output_icon = &Image {
set_icon_name: Some("audio-speakers-symbolic"),
},
append: output_volume = &Scale::with_range(Orientation::Horizontal, 0., 100., 1.) {
set_format_value_func: |_, value| {
format!("{:.0}%", value)
},
set_value_pos: PositionType::Right,
set_hexpand: true
}
},
append: input_box = &GtkBox {
set_orientation: Orientation::Horizontal,
set_spacing: 16,
append: input_icon = &Image {
set_icon_name: Some("audio-input-microphone-symbolic"),
},
append: input_volume = &Scale::with_range(Orientation::Horizontal, 0., 100., 1.) {
set_format_value_func: |_, value| {
format!("{:.0}%", value)
},
set_value_pos: PositionType::Right,
set_hexpand: true
}
},
append: _sep = &Separator {
set_orientation: Orientation::Horizontal,
},
append: output_list_box = &GtkBox {
set_child = &libcosmic_applet::AppletButton {
// TODO: adjust based on volume, mute
set_button_icon_name: "multimedia-volume-control-symbolic",
#[wrap(Some)]
set_popover_child: window_box = &GtkBox {
set_orientation: Orientation::Vertical,
append: current_output_button = &Button {
#[wrap(Some)]
set_child: current_output = &Label {},
connect_clicked[outputs_revealer] => move |_| {
outputs_revealer.set_reveal_child(!outputs_revealer.reveals_child());
set_spacing: 24,
append: output_box = &GtkBox {
set_orientation: Orientation::Horizontal,
set_spacing: 16,
append: output_icon = &Image {
set_icon_name: Some("audio-speakers-symbolic"),
},
append: output_volume = &Scale::with_range(Orientation::Horizontal, 0., 100., 1.) {
set_format_value_func: |_, value| {
format!("{:.0}%", value)
},
set_value_pos: PositionType::Right,
set_hexpand: true
}
},
append: outputs_revealer = &Revealer {
set_transition_type: RevealerTransitionType::SlideDown,
#[wrap(Some)]
set_child: outputs = &ListBox {
set_selection_mode: SelectionMode::None,
set_activate_on_single_click: true
}
}
},
append: _sep = &Separator {
set_orientation: Orientation::Horizontal,
},
append: input_list_box = &GtkBox {
set_orientation: Orientation::Vertical,
append: current_input_button = &Button {
#[wrap(Some)]
set_child: current_input = &Label {},
connect_clicked[inputs_revealer] => move |_| {
inputs_revealer.set_reveal_child(!inputs_revealer.reveals_child());
append: input_box = &GtkBox {
set_orientation: Orientation::Horizontal,
set_spacing: 16,
append: input_icon = &Image {
set_icon_name: Some("audio-input-microphone-symbolic"),
},
append: input_volume = &Scale::with_range(Orientation::Horizontal, 0., 100., 1.) {
set_format_value_func: |_, value| {
format!("{:.0}%", value)
},
set_value_pos: PositionType::Right,
set_hexpand: true
}
},
append: inputs_revealer = &Revealer {
set_transition_type: RevealerTransitionType::SlideDown,
#[wrap(Some)]
set_child: inputs = &ListBox {
set_selection_mode: SelectionMode::None,
set_activate_on_single_click: true
append: _sep = &Separator {
set_orientation: Orientation::Horizontal,
},
append: output_list_box = &GtkBox {
set_orientation: Orientation::Vertical,
append: current_output_button = &Button {
#[wrap(Some)]
set_child: current_output = &Label {},
connect_clicked[outputs_revealer] => move |_| {
outputs_revealer.set_reveal_child(!outputs_revealer.reveals_child());
}
},
append: outputs_revealer = &Revealer {
set_transition_type: RevealerTransitionType::SlideDown,
#[wrap(Some)]
set_child: outputs = &ListBox {
set_selection_mode: SelectionMode::None,
set_activate_on_single_click: true
}
}
},
append: _sep = &Separator {
set_orientation: Orientation::Horizontal,
},
append: input_list_box = &GtkBox {
set_orientation: Orientation::Vertical,
append: current_input_button = &Button {
#[wrap(Some)]
set_child: current_input = &Label {},
connect_clicked[inputs_revealer] => move |_| {
inputs_revealer.set_reveal_child(!inputs_revealer.reveals_child());
}
},
append: inputs_revealer = &Revealer {
set_transition_type: RevealerTransitionType::SlideDown,
#[wrap(Some)]
set_child: inputs = &ListBox {
set_selection_mode: SelectionMode::None,
set_activate_on_single_click: true
}
}
},
append: _sep = &Separator {
set_orientation: Orientation::Horizontal,
},
append: playing_apps = &ListBox {
set_selection_mode: SelectionMode::None,
}
},
append: _sep = &Separator {
set_orientation: Orientation::Horizontal,
},
append: playing_apps = &ListBox {
set_selection_mode: SelectionMode::None,
}
}
}

View file

@ -57,6 +57,7 @@ struct AppModel {
kbd_backlight: Option<KbdBacklightProxy<'static>>,
}
#[derive(Debug)]
enum AppMsg {
SetDisplayBrightness(f64),
SetKeyboardBrightness(f64),
@ -77,115 +78,118 @@ impl SimpleComponent for AppModel {
type Output = ();
view! {
libcosmic_applet::Applet {
#[watch]
set_button_icon_name: &model.icon_name,
libcosmic_applet::AppletWindow {
#[wrap(Some)]
set_popover_child = &gtk4::Box {
set_orientation: gtk4::Orientation::Vertical,
set_child = &libcosmic_applet::AppletButton {
#[watch]
set_button_icon_name: &model.icon_name,
#[wrap(Some)]
set_popover_child = &gtk4::Box {
set_orientation: gtk4::Orientation::Vertical,
// Battery
gtk4::Box {
set_orientation: gtk4::Orientation::Horizontal,
gtk4::Image {
#[watch]
set_icon_name: Some(&model.icon_name),
},
// Battery
gtk4::Box {
set_orientation: gtk4::Orientation::Vertical,
gtk4::Label {
set_halign: gtk4::Align::Start,
set_label: "Battery",
},
gtk4::Label {
set_halign: gtk4::Align::Start,
// XXX time to full, fully changed, etc.
set_orientation: gtk4::Orientation::Horizontal,
gtk4::Image {
#[watch]
set_label: &format!("{} until empty ({:.0}%)", format_duration(model.time_remaining), model.battery_percent),
set_icon_name: Some(&model.icon_name),
},
gtk4::Box {
set_orientation: gtk4::Orientation::Vertical,
gtk4::Label {
set_halign: gtk4::Align::Start,
set_label: "Battery",
},
gtk4::Label {
set_halign: gtk4::Align::Start,
// XXX time to full, fully changed, etc.
#[watch]
set_label: &format!("{} until empty ({:.0}%)", format_duration(model.time_remaining), model.battery_percent),
},
},
},
},
gtk4::Separator {
},
gtk4::Separator {
},
// Limit charging
gtk4::Box {
set_orientation: gtk4::Orientation::Horizontal,
// Limit charging
gtk4::Box {
set_orientation: gtk4::Orientation::Vertical,
gtk4::Label {
set_halign: gtk4::Align::Start,
set_label: "Limit Battery Charging",
set_orientation: gtk4::Orientation::Horizontal,
gtk4::Box {
set_orientation: gtk4::Orientation::Vertical,
gtk4::Label {
set_halign: gtk4::Align::Start,
set_label: "Limit Battery Charging",
},
gtk4::Label {
set_halign: gtk4::Align::Start,
set_label: "Increase the lifespan of your battery by setting a maximum charge value of 80%."
},
},
gtk4::Switch {
set_valign: gtk4::Align::Center,
},
},
gtk4::Separator {
},
// Brightness
gtk4::Box {
#[watch]
set_visible: model.backlight.is_some(),
set_orientation: gtk4::Orientation::Horizontal,
gtk4::Image {
set_icon_name: Some("display-brightness-symbolic"),
},
gtk4::Scale {
set_hexpand: true,
set_adjustment: &gtk4::Adjustment::new(0., 0., 1., 1., 1., 0.),
#[watch]
set_value: model.display_brightness,
connect_change_value[sender] => move |_, _, value| {
sender.input(AppMsg::SetDisplayBrightness(value));
gtk4::Inhibit(false)
},
},
gtk4::Label {
set_halign: gtk4::Align::Start,
set_label: "Increase the lifespan of your battery by setting a maximum charge value of 80%."
#[watch]
set_label: &format!("{:.0}%", model.display_brightness * 100.),
},
},
gtk4::Switch {
set_valign: gtk4::Align::Center,
},
},
gtk4::Separator {
},
// Brightness
gtk4::Box {
#[watch]
set_visible: model.backlight.is_some(),
set_orientation: gtk4::Orientation::Horizontal,
gtk4::Image {
set_icon_name: Some("display-brightness-symbolic"),
},
gtk4::Scale {
set_hexpand: true,
set_adjustment: &gtk4::Adjustment::new(0., 0., 1., 1., 1., 0.),
gtk4::Box {
#[watch]
set_value: model.display_brightness,
connect_change_value[sender] => move |_, _, value| {
sender.input(AppMsg::SetDisplayBrightness(value));
gtk4::Inhibit(false)
set_visible: model.kbd_backlight.is_some(),
set_orientation: gtk4::Orientation::Horizontal,
gtk4::Image {
set_icon_name: Some("keyboard-brightness-symbolic"),
},
gtk4::Scale {
set_hexpand: true,
set_adjustment: &gtk4::Adjustment::new(0., 0., 1., 1., 1., 0.),
#[watch]
set_value: model.keyboard_brightness,
connect_change_value[sender] => move |_, _, value| {
sender.input(AppMsg::SetKeyboardBrightness(value));
gtk4::Inhibit(false)
},
},
gtk4::Label {
#[watch]
set_label: &format!("{:.0}%", model.keyboard_brightness * 100.),
},
},
gtk4::Label {
#[watch]
set_label: &format!("{:.0}%", model.display_brightness * 100.),
},
},
gtk4::Box {
#[watch]
set_visible: model.kbd_backlight.is_some(),
set_orientation: gtk4::Orientation::Horizontal,
gtk4::Image {
set_icon_name: Some("keyboard-brightness-symbolic"),
},
gtk4::Scale {
set_hexpand: true,
set_adjustment: &gtk4::Adjustment::new(0., 0., 1., 1., 1., 0.),
#[watch]
set_value: model.keyboard_brightness,
connect_change_value[sender] => move |_, _, value| {
sender.input(AppMsg::SetKeyboardBrightness(value));
gtk4::Inhibit(false)
},
},
gtk4::Label {
#[watch]
set_label: &format!("{:.0}%", model.keyboard_brightness * 100.),
},
},
gtk4::Separator {
},
gtk4::Separator {
},
gtk4::Button {
set_label: "Power Settings...",
connect_clicked => move |_| {
// XXX open subpanel
let _ = Command::new("cosmic-settings").spawn();
// TODO hide
gtk4::Button {
set_label: "Power Settings...",
connect_clicked => move |_| {
// XXX open subpanel
let _ = Command::new("cosmic-settings").spawn();
// TODO hide
}
}
}
}

View file

@ -7,8 +7,8 @@ edition = "2021"
[dependencies]
gtk4 = { git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_2"] }
libcosmic-applet = { path = "../../libcosmic-applet" }
once_cell = "1.9.0"
relm4-macros = { git = "https://github.com/Relm4/Relm4.git", branch = "next" }
tokio = { version = "1.16.1", features = ["full"] }
zbus = "2.1.1"
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"], branch = "rework_0.30"}

View file

@ -11,28 +11,15 @@ pub mod mode_box;
use self::{dbus::PowerDaemonProxy, graphics::Graphics, mode_box::ModeSelection};
use gtk4::{
gdk::Display,
gio::ApplicationFlags,
glib::{self, clone, MainContext, PRIORITY_DEFAULT},
prelude::*,
Align, CssProvider, Label, ListBox, ListBoxRow, Orientation, Overlay, Separator, Spinner,
StyleContext, STYLE_PROVIDER_PRIORITY_APPLICATION,
Align, Label, ListBox, ListBoxRow, Orientation, Overlay, Separator, Spinner,
};
use once_cell::sync::Lazy;
use tokio::runtime::Runtime;
use cosmic_panel_config::CosmicPanelConfig;
static RT: Lazy<Runtime> = Lazy::new(|| Runtime::new().expect("failed to build tokio runtime"));
fn main() {
let application = gtk4::Application::new(
Some("com.system76.cosmic.applets.graphics"),
ApplicationFlags::default(),
);
application.connect_activate(build_ui);
application.run();
}
async fn get_current_graphics() -> zbus::Result<Graphics> {
let connection = zbus::Connection::system().await?;
let proxy = PowerDaemonProxy::new(&connection).await?;
@ -53,7 +40,9 @@ fn row_clicked(_: &ListBox, row: &ListBoxRow) {
selector.emit_activate();
}
fn build_ui(application: &gtk4::Application) {
fn main() {
gtk4::init().unwrap();
let provider = gtk4::CssProvider::new();
provider.load_from_data(include_bytes!("style.css"));
gtk4::StyleContext::add_provider_for_display(
@ -62,141 +51,119 @@ fn build_ui(application: &gtk4::Application) {
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
let window = gtk4::ApplicationWindow::builder()
.application(application)
.title("COSMIC Graphics Applet")
.decorated(false)
.resizable(false)
.width_request(1)
.height_request(1)
.css_classes(vec!["root_window".to_string()])
.build();
let config = CosmicPanelConfig::load_from_env().unwrap_or_default();
let popover = gtk4::builders::PopoverBuilder::new()
.autohide(true)
.has_arrow(false)
.build();
let button = gtk4::Button::new();
button.add_css_class("panel_icon");
button.connect_clicked(glib::clone!(@weak popover => move |_| {
popover.show();
}));
// TODO cleanup
let image = gtk4::Image::from_icon_name("input-gaming");
image.add_css_class("panel_icon");
image.set_pixel_size(config.get_applet_icon_size().try_into().unwrap());
button.set_child(Some(&image));
let current_graphics = RT
let current_graphics = RT
.block_on(get_current_graphics())
.expect("failed to connect to system76-power");
view! {
icon_box = gtk4::Box {
set_orientation: Orientation::Vertical,
set_spacing: 0,
add_css_class: "icon_box",
}
}
let (tx, rx) = MainContext::channel::<bool>(PRIORITY_DEFAULT);
view! {
main_overlay = Overlay {
add_overlay: loading_box = &gtk4::Box {
append: loading_explain_box = &gtk4::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",
},
window = libcosmic_applet::AppletWindow {
set_title: Some("COSMIC Graphics Applet"),
#[wrap(Some)]
set_child: main_box = &gtk4::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");
});
})
set_child = &libcosmic_applet::AppletButton {
set_button_icon_name: "input-gaming",
#[wrap(Some)]
set_popover_child: main_overlay = &Overlay {
add_overlay: loading_box = &gtk4::Box {
append: loading_explain_box = &gtk4::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 = &gtk4::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| {
@ -205,11 +172,9 @@ fn build_ui(application: &gtk4::Application) {
Continue(true)
}),
);
popover.set_child(Some(&main_overlay));
icon_box.append(&button);
icon_box.append(&popover);
window.set_child(Some(&icon_box));
window.show();
let main_loop = glib::MainLoop::new(None, false);
main_loop.run();
}

View file

@ -2,32 +2,3 @@
background-color: #2f2f2f;
opacity: 0.85;
}
image.panel_icon {
padding-left: 0px;
padding-right: 0px;
padding-top: 0px;
padding-bottom: 0px;
}
button.panel_icon {
border-radius: 12px;
transition: 100ms;
padding: 4px;
border-color: transparent;
background: transparent;
outline-color: transparent;
}
button.panel_icon:hover {
border-radius: 12px;
transition: 100ms;
padding: 4px;
border-color: rgba(255, 255, 255, 0.1);
outline-color: rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.1);
}
window.root_window {
background: transparent;
}

View file

@ -14,5 +14,5 @@ relm4-macros = { git = "https://github.com/Relm4/Relm4.git", branch = "next" }
slotmap = "1.0.6"
tokio = { version = "1.15.0", features = ["full"] }
zbus = "2.0.1"
libcosmic-applet = { path = "../../libcosmic-applet" }
libcosmic-widgets = { git = "https://github.com/pop-os/libcosmic", branch = "relm4-next" }
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"], branch = "rework_0.30"}

View file

@ -7,90 +7,43 @@ pub mod task;
pub mod ui;
pub mod widgets;
use cosmic_panel_config::CosmicPanelConfig;
use gtk4::{gio::ApplicationFlags, glib, prelude::*, Orientation, Separator};
use gtk4::{glib, prelude::*, Orientation, Separator};
use once_cell::sync::Lazy;
use tokio::runtime::Runtime;
static RT: Lazy<Runtime> = Lazy::new(|| Runtime::new().expect("failed to build tokio runtime"));
fn main() {
let application = gtk4::Application::new(
Some("com.system76.cosmic.applets.network"),
ApplicationFlags::default(),
);
application.connect_activate(build_ui);
application.run();
}
fn build_ui(application: &gtk4::Application) {
let provider = gtk4::CssProvider::new();
provider.load_from_data(include_bytes!("style.css"));
gtk4::StyleContext::add_provider_for_display(
&gtk4::gdk::Display::default().expect("Could not connect to a display."),
&provider,
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
let window = gtk4::ApplicationWindow::builder()
.application(application)
.title("COSMIC Network Applet")
.decorated(false)
.resizable(false)
.width_request(1)
.height_request(1)
.css_classes(vec!["root_window".to_string()])
.build();
gtk4::init().unwrap();
view! {
main_box = gtk4::Box {
set_orientation: Orientation::Vertical,
set_spacing: 10,
set_margin_top: 20,
set_margin_bottom: 20,
set_margin_start: 24,
set_margin_end: 24
window = libcosmic_applet::AppletWindow {
set_title: Some("COSMIC Network Applet"),
#[wrap(Some)]
set_child: button = &libcosmic_applet::AppletButton {
set_button_icon_name: "preferences-system-network",
#[wrap(Some)]
set_popover_child: main_box = &gtk4::Box {
set_orientation: Orientation::Vertical,
set_spacing: 10,
set_margin_top: 20,
set_margin_bottom: 20,
set_margin_start: 24,
set_margin_end: 24
}
}
}
}
let config = CosmicPanelConfig::load_from_env().unwrap_or_default();
let popover = gtk4::builders::PopoverBuilder::new()
.autohide(true)
.has_arrow(false)
.build();
let button = gtk4::Button::new();
button.add_css_class("panel_icon");
button.connect_clicked(glib::clone!(@weak popover => move |_| {
popover.show();
}));
// TODO cleanup
let image = gtk4::Image::from_icon_name("preferences-system-network");
image.add_css_class("panel_icon");
image.set_pixel_size(config.get_applet_icon_size().try_into().unwrap());
button.set_child(Some(&image));
view! {
icon_box = gtk4::Box {
set_orientation: Orientation::Vertical,
set_spacing: 0,
add_css_class: "icon_box",
}
}
popover.set_child(Some(&main_box));
icon_box.append(&button);
icon_box.append(&popover);
ui::current_networks::add_current_networks(&main_box, &image);
ui::current_networks::add_current_networks(&main_box, &button);
main_box.append(&Separator::new(Orientation::Horizontal));
ui::toggles::add_toggles(&main_box);
let available_wifi_separator = Separator::new(Orientation::Horizontal);
main_box.append(&available_wifi_separator);
available_wifi_separator.hide();
ui::available_wifi::add_available_wifi(&main_box, available_wifi_separator);
window.set_child(Some(&icon_box));
window.show();
let main_loop = glib::MainLoop::new(None, false);
main_loop.run();
}

View file

@ -1,28 +0,0 @@
image.panel_icon {
padding-left: 0px;
padding-right: 0px;
padding-top: 0px;
padding-bottom: 0px;
}
button.panel_icon {
border-radius: 12px;
transition: 100ms;
padding: 4px;
border-color: transparent;
background: transparent;
outline-color: transparent;
}
button.panel_icon:hover {
border-radius: 12px;
transition: 100ms;
padding: 4px;
border-color: rgba(255, 255, 255, 0.1);
outline-color: rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.1);
}
window.root_window {
background: transparent;
}

View file

@ -18,7 +18,7 @@ use gtk4::{
use std::{cell::RefCell, net::IpAddr, rc::Rc};
use zbus::Connection;
pub fn add_current_networks(target: &gtk4::Box, icon_image: &gtk4::Image) {
pub fn add_current_networks(target: &gtk4::Box, icon_image: &libcosmic_applet::AppletButton) {
let networks_list = ListBox::builder().show_separators(true).build();
let entries = Rc::<RefCell<Vec<ListBoxRow>>>::default();
let (tx, rx) = MainContext::channel::<Vec<ActiveConnectionInfo>>(PRIORITY_DEFAULT);
@ -38,7 +38,7 @@ fn display_active_connections(
connections: Vec<ActiveConnectionInfo>,
target: &ListBox,
entries: &mut Vec<ListBoxRow>,
icon_image: &gtk4::Image,
icon_image: &libcosmic_applet::AppletButton,
) {
for old_entry in entries.drain(..) {
target.remove(&old_entry);
@ -51,7 +51,7 @@ fn display_active_connections(
speed,
ip_addresses,
} => {
icon_image.set_icon_name(Some("network-wired-symbolic"));
icon_image.set_button_icon_name("network-wired-symbolic");
render_wired_connection(name, speed, ip_addresses)
}
ActiveConnectionInfo::WiFi {
@ -62,7 +62,7 @@ fn display_active_connections(
wpa_flags,
} => continue,
ActiveConnectionInfo::Vpn { name, ip_addresses } => {
icon_image.set_icon_name(Some("network-vpn-symbolic"));
icon_image.set_button_icon_name("network-vpn-symbolic");
render_vpn(name, ip_addresses)
}
};

View file

@ -10,8 +10,8 @@ futures = "0.3"
gtk4 = { git = "https://github.com/gtk-rs/gtk4-rs" }
libcosmic-applet = { path = "../../libcosmic-applet" }
once_cell = "1.12"
relm4-macros = { git = "https://github.com/Relm4/Relm4.git", branch = "next" }
serde = "1"
zbus = "2.0.1"
zbus_names = "2"
zvariant = "3"
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"], branch = "rework_0.30"}

View file

@ -1,5 +1,5 @@
use cascade::cascade;
use gtk4::{glib, prelude::*};
use relm4_macros::view;
mod dbus_service;
mod deref_cell;
@ -19,18 +19,20 @@ fn main() {
let notification_list = NotificationList::new(&notifications);
let window = cascade! {
libcosmic_applet::Applet::new();
..set_button_icon_name("user-invisible-symbolic"); // TODO
..set_popover_child(Some(&notification_list));
..show();
};
view! {
window = libcosmic_applet::AppletWindow {
#[wrap(Some)]
set_child: applet_button = &libcosmic_applet::AppletButton {
set_button_icon_name: "user-invisible-symbolic", // TODO
set_popover_child: Some(&notification_list)
}
}
}
window.show();
// XXX show in correct place
cascade! {
NotificationPopover::new(&notifications);
..set_parent(&window.child().unwrap()); // XXX better way?
};
let notification_popover = NotificationPopover::new(&notifications);
notification_popover.set_parent(&applet_button);
let main_loop = glib::MainLoop::new(None, false);
main_loop.run();

View file

@ -24,34 +24,37 @@ fn main() {
fn build_ui(application: &gtk4::Application) {
view! {
window = libcosmic_applet::Applet {
window = libcosmic_applet::AppletWindow {
set_title: Some("COSMIC Power Applet"),
set_application: Some(application),
// TODO adjust battery icon based on charge
set_button_icon_name: "system-shutdown-symbolic",
#[wrap(Some)]
set_popover_child: main_box = &gtk4::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: settings_button = &Button {
#[wrap(Some)]
set_child = &Label {
set_label: "Settings...",
set_halign: Align::Start,
set_hexpand: true
set_child = &libcosmic_applet::AppletButton {
set_button_icon_name: "system-shutdown-symbolic",
#[wrap(Some)]
set_popover_child: main_box = &gtk4::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: settings_button = &Button {
#[wrap(Some)]
set_child = &Label {
set_label: "Settings...",
set_halign: Align::Start,
set_hexpand: true
},
connect_clicked => move |_| {
let _ = Command::new("cosmic-settings").spawn();
}
},
connect_clicked => move |_| {
let _ = Command::new("cosmic-settings").spawn();
}
},
append = &Separator {},
append: &ui::session::build(),
append: second_separator = &Separator {},
append: &ui::system::build(),
append = &Separator {},
append: &ui::session::build(),
append: second_separator = &Separator {},
append: &ui::system::build(),
}
}
}
}

View file

@ -8,9 +8,9 @@ license = "GPL-3.0-or-later"
cascade = "1"
futures = "0.3"
gtk4 = { git = "https://github.com/gtk-rs/gtk4-rs" }
libcosmic-applet = { path = "../../libcosmic-applet" }
once_cell = "1.12"
serde = "1"
zbus = "2.0.1"
zbus_names = "2"
zvariant = "3"
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"], branch = "rework_0.30"}

View file

@ -1,3 +1,4 @@
use cascade::cascade;
use gtk4::{glib, prelude::*};
mod dbus_service;
@ -14,24 +15,12 @@ fn main() {
// XXX Implement DBus service somewhere other than applet?
glib::MainContext::default().spawn_local(status_notifier_watcher::start());
let provider = gtk4::CssProvider::new();
provider.load_from_data(include_bytes!("style.css"));
gtk4::StyleContext::add_provider_for_display(
&gtk4::gdk::Display::default().expect("Could not connect to a display."),
&provider,
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
let status_area = StatusArea::new();
gtk4::Window::builder()
.decorated(false)
.child(&status_area)
.resizable(false)
.width_request(1)
.height_request(1)
.css_classes(vec!["root_window".to_string()])
.build()
.show();
cascade! {
libcosmic_applet::AppletWindow::new();
..set_child(Some(&status_area));
..show();
};
let main_loop = glib::MainLoop::new(None, false);
main_loop.run();

View file

@ -19,7 +19,7 @@ struct Menu {
#[derive(Default)]
pub struct StatusMenuInner {
menu_button: DerefCell<gtk4::MenuButton>,
menu_button: DerefCell<libcosmic_applet::AppletButton>,
vbox: DerefCell<gtk4::Box>,
item: DerefCell<StatusNotifierItemProxy<'static>>,
dbus_menu: DerefCell<DBusMenuProxy<'static>>,
@ -43,17 +43,10 @@ impl ObjectImpl for StatusMenuInner {
gtk4::Box::new(gtk4::Orientation::Vertical, 0);
};
let popover = cascade! {
gtk4::Popover::new();
..set_child(Some(&vbox));
};
let menu_button = cascade! {
gtk4::MenuButton::new();
..add_css_class("panel_icon");
..set_has_frame(false);
libcosmic_applet::AppletButton::new();
..set_parent(obj);
..set_popover(Some(&popover));
..set_popover_child(Some(&vbox));
};
self.menu_button.set(menu_button);
@ -88,7 +81,7 @@ impl StatusMenu {
.await?;
let obj = glib::Object::new::<Self>(&[]).unwrap();
let icon_name = item.icon_name().await?;
obj.inner().menu_button.set_icon_name(&icon_name);
obj.inner().menu_button.set_button_icon_name(&icon_name);
let menu = item.menu().await?;
let menu = DBusMenuProxy::builder(&connection)

View file

@ -1,33 +0,0 @@
.loading-overlay {
background-color: #2f2f2f;
opacity: 0.85;
}
image.panel_icon {
padding-left: 0px;
padding-right: 0px;
padding-top: 0px;
padding-bottom: 0px;
}
button.panel_icon {
border-radius: 12px;
transition: 100ms;
padding: 4px;
border-color: transparent;
background: transparent;
outline-color: transparent;
}
button.panel_icon:hover {
border-radius: 12px;
transition: 100ms;
padding: 4px;
border-color: rgba(255, 255, 255, 0.1);
outline-color: rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.1);
}
window.root_window {
background: transparent;
}

View file

@ -9,9 +9,9 @@ cascade = "1"
chrono = "0.4"
futures = "0.3"
gtk4 = { git = "https://github.com/gtk-rs/gtk4-rs", features = [ "v4_6" ] }
libcosmic-applet = { path = "../../libcosmic-applet" }
once_cell = "1.12"
serde = "1"
zbus = "2.0.1"
zbus_names = "2"
zvariant = "3"
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"], branch = "rework_0.30"}

View file

@ -1,3 +1,4 @@
use cascade::cascade;
use gtk4::{glib, prelude::*};
mod deref_cell;
@ -7,25 +8,11 @@ use time_button::TimeButton;
fn main() {
gtk4::init().unwrap();
let provider = gtk4::CssProvider::new();
provider.load_from_data(include_bytes!("style.css"));
gtk4::StyleContext::add_provider_for_display(
&gtk4::gdk::Display::default().expect("Could not connect to a display."),
&provider,
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
let time_button = TimeButton::new();
gtk4::Window::builder()
.decorated(false)
.child(&time_button)
.resizable(false)
.width_request(1)
.height_request(1)
.css_classes(vec!["root_window".to_string()])
.build()
.show();
cascade! {
libcosmic_applet::AppletWindow::new();
..set_child(Some(&TimeButton::new()));
..show();
};
let main_loop = glib::MainLoop::new(None, false);
main_loop.run();

View file

@ -1,33 +0,0 @@
.loading-overlay {
background-color: #2f2f2f;
opacity: 0.85;
}
image.panel_icon {
padding-left: 0px;
padding-right: 0px;
padding-top: 0px;
padding-bottom: 0px;
}
button.panel_icon {
border-radius: 12px;
transition: 100ms;
padding: 4px;
border-color: transparent;
background: transparent;
outline-color: transparent;
}
button.panel_icon:hover {
border-radius: 12px;
transition: 100ms;
padding: 4px;
border-color: rgba(255, 255, 255, 0.1);
outline-color: rgba(255, 255, 255, 0.1);
background: rgba(255, 255, 255, 0.1);
}
window.root_window {
background: transparent;
}

View file

@ -11,7 +11,7 @@ use crate::deref_cell::DerefCell;
#[derive(Default)]
pub struct TimeButtonInner {
calendar: DerefCell<gtk4::Calendar>,
button: DerefCell<gtk4::MenuButton>,
button: DerefCell<libcosmic_applet::AppletButton>,
label: DerefCell<gtk4::Label>,
}
@ -40,21 +40,15 @@ impl ObjectImpl for TimeButtonInner {
}));
};
let popover = cascade! {
gtk4::Popover::new();
..set_child(Some(&cascade! {
let button = cascade! {
libcosmic_applet::AppletButton::new();
..set_parent(obj);
..connect_activate(clone!(@strong obj => move |_| obj.opening()));
..set_button_child(Some(&label));
..set_popover_child(Some(&cascade! {
gtk4::Box::new(gtk4::Orientation::Horizontal, 0);
..append(&calendar);
}));
..connect_show(clone!(@strong obj => move |_| obj.opening()));
};
let button = cascade! {
gtk4::MenuButton::new();
..set_child(Some(&label));
..set_has_frame(false);
..set_parent(obj);
..set_popover(Some(&popover));
};
self.calendar.set(calendar);

View file

@ -7,7 +7,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"], branch = "rework_0.30"}
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"] }
cascade = "1.0.0"
gtk4 = { git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_4"] }
once_cell = "1.9.0"

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: MPL-2.0-only
use calloop::channel::SyncSender;
use gtk4::{
gdk::Display,
gio::{self, ApplicationFlags},
@ -13,7 +14,6 @@ use tokio::sync::mpsc;
use utils::{Activate, WorkspaceEvent};
use wayland::State;
use window::CosmicWorkspacesWindow;
use calloop::channel::SyncSender;
mod localize;
mod utils;

View file

@ -92,8 +92,8 @@ pub fn spawn_workspaces(tx: glib::Sender<State>) -> SyncSender<WorkspaceEvent> {
running: true,
};
let loop_handle = event_loop.handle();
loop_handle.insert_source(workspaces_rx, |e, _, state| {
match e {
loop_handle
.insert_source(workspaces_rx, |e, _, state| match e {
Event::Msg(WorkspaceEvent::Activate(id)) => {
if let Some(w) = state
.workspace_groups
@ -136,15 +136,16 @@ pub fn spawn_workspaces(tx: glib::Sender<State>) -> SyncSender<WorkspaceEvent> {
}
}
}
Event::Closed => if let Some(workspace_manager) = &mut state.workspace_manager {
for g in &mut state.workspace_groups {
g.workspace_group_handle.destroy();
Event::Closed => {
if let Some(workspace_manager) = &mut state.workspace_manager {
for g in &mut state.workspace_groups {
g.workspace_group_handle.destroy();
}
workspace_manager.stop();
}
workspace_manager.stop();
},
}
}).unwrap();
}
})
.unwrap();
while state.running {
event_loop
.dispatch(Duration::from_millis(16), &mut state)

View file

@ -43,9 +43,7 @@ impl WorkspaceButton {
new_button.connect_clicked(move |_| {
let id_clone = id.clone();
if !is_active {
let _ = TX.get()
.unwrap()
.send(WorkspaceEvent::Activate(id_clone));
let _ = TX.get().unwrap().send(WorkspaceEvent::Activate(id_clone));
}
});

View file

@ -61,9 +61,7 @@ impl WorkspaceList {
.build();
scroll_controller.connect_scroll(|_, dx, dy| {
let _ = TX.get()
.unwrap()
.send(WorkspaceEvent::Scroll(dx + dy));
let _ = TX.get().unwrap().send(WorkspaceEvent::Scroll(dx + dy));
Inhibit::default()
});

View file

@ -5,7 +5,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"], branch = "rework_0.30"}
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"] }
cascade = "1.0.0"
gtk4 = { git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_4"] }
once_cell = "1.9.0"

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"], branch = "rework_0.30"}
cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel", features = ["gtk4"] }
gtk4 = { git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_6"] }
once_cell = "1.12.0"
relm4-macros = { git = "https://github.com/Relm4/Relm4.git", branch = "next" }

View file

@ -0,0 +1,143 @@
use cosmic_panel_config::CosmicPanelConfig;
use gtk4::{glib, prelude::*, subclass::prelude::*};
use relm4_macros::view;
use crate::deref_cell::DerefCell;
static STYLE: &str = "
button.cosmic_applet_button {
border-radius: 12px;
transition: 100ms;
padding: 4px;
border-color: transparent;
background: transparent;
outline-color: transparent;
}
";
#[derive(Default)]
pub struct AppletButtonInner {
menu_button: DerefCell<gtk4::MenuButton>,
panel_config: DerefCell<CosmicPanelConfig>,
popover: DerefCell<gtk4::Popover>,
}
#[glib::object_subclass]
impl ObjectSubclass for AppletButtonInner {
const NAME: &'static str = "CosmicAppletButton";
type Type = AppletButton;
type ParentType = gtk4::Widget;
}
impl ObjectImpl for AppletButtonInner {
fn constructed(&self, obj: &AppletButton) {
view! {
menu_button = gtk4::MenuButton {
set_parent: obj,
add_css_class: "cosmic_applet_button",
set_has_frame: false,
#[wrap(Some)]
set_popover: popover = &gtk4::Popover {
// TODO: change if it can be positioned correctly?
set_has_arrow: false,
}
},
provider = gtk4::CssProvider {
load_from_data: STYLE.as_bytes(),
}
}
obj.set_layout_manager(Some(&gtk4::BinLayout::new()));
obj.style_context()
.add_provider(&provider, gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION);
self.menu_button.set(menu_button);
self.popover.set(popover);
self.panel_config
.set(CosmicPanelConfig::load_from_env().unwrap_or_default());
}
fn dispose(&self, _obj: &AppletButton) {
self.menu_button.unparent();
}
}
impl WidgetImpl for AppletButtonInner {
fn compute_expand(&self, _obj: &AppletButton, hexpand: &mut bool, vexpand: &mut bool) {
*hexpand = self
.menu_button
.compute_expand(gtk4::Orientation::Horizontal);
*vexpand = self.menu_button.compute_expand(gtk4::Orientation::Vertical);
}
fn request_mode(&self, _obj: &AppletButton) -> gtk4::SizeRequestMode {
self.menu_button.request_mode()
}
}
impl WindowImpl for AppletButtonInner {}
glib::wrapper! {
pub struct AppletButton(ObjectSubclass<AppletButtonInner>)
@extends gtk4::Widget;
}
impl Default for AppletButton {
fn default() -> Self {
Self::new()
}
}
impl AppletButton {
pub fn new() -> Self {
glib::Object::new(&[]).unwrap()
}
fn inner(&self) -> &AppletButtonInner {
AppletButtonInner::from_instance(self)
}
// TODO: avoid multiple instances?
pub fn panel_config(&self) -> &CosmicPanelConfig {
&*self.inner().panel_config
}
pub fn set_button_child(&self, child: Option<&impl IsA<gtk4::Widget>>) {
self.inner().menu_button.set_child(child);
}
pub fn set_button_icon_name(&self, name: &str) {
let image = gtk4::Image::from_icon_name(name);
image.set_pixel_size(
self.panel_config()
.get_applet_icon_size()
.try_into()
.unwrap(),
); // XXX unwrap
self.set_button_child(Some(&image));
}
pub fn set_button_label(&self, label: &str) {
self.inner().menu_button.set_label(label);
}
pub fn set_popover_child(&self, child: Option<&impl IsA<gtk4::Widget>>) {
self.inner().popover.set_child(child);
}
pub fn popdown(&self) {
self.inner().popover.popdown();
}
pub fn popup(&self) {
self.inner().popover.popup();
}
// XXX better API? Actual signal
pub fn connect_activate<F: Fn(&Self) + 'static>(&self, f: F) -> glib::SignalHandlerId {
self.inner()
.menu_button
.connect_activate(glib::clone!(@weak self as _self => move |_| {
f(&_self)
}))
}
}

View file

@ -2,8 +2,11 @@ use cosmic_panel_config::CosmicPanelConfig;
use gtk4::{glib, prelude::*, subclass::prelude::*};
use relm4_macros::view;
mod button;
pub use button::AppletButton;
mod deref_cell;
use deref_cell::DerefCell;
mod window;
pub use window::AppletWindow;
// TODO make sure style fits different panel colors?
// TODO abstraction to start main loop? Work with relm4.
@ -11,118 +14,4 @@ use deref_cell::DerefCell;
// TODO orientation, etc.
// TODO make image size dependent on CosmicPanelConfig?
// TODO way to have multiple applets with this style, for system tray.
static STYLE: &str = "
window.cosmic_applet_window {
background: transparent;
}
button.cosmic_applet_button {
border-radius: 12px;
transition: 100ms;
padding: 4px;
border-color: transparent;
background: transparent;
outline-color: transparent;
}
";
#[derive(Default)]
pub struct AppletInner {
panel_config: DerefCell<CosmicPanelConfig>,
menu_button: DerefCell<gtk4::MenuButton>,
popover: DerefCell<gtk4::Popover>,
}
#[glib::object_subclass]
impl ObjectSubclass for AppletInner {
const NAME: &'static str = "CosmicApplet";
type Type = Applet;
type ParentType = gtk4::Window;
}
impl ObjectImpl for AppletInner {
fn constructed(&self, obj: &Applet) {
let window = || obj;
view! {
window() {
add_css_class: "cosmic_applet_window",
set_decorated: false,
set_resizable: false,
set_width_request: 1,
set_height_request: 1,
#[wrap(Some)]
set_child: menu_button = &gtk4::MenuButton {
add_css_class: "cosmic_applet_button",
set_has_frame: false,
#[wrap(Some)]
set_popover: popover = &gtk4::Popover {
// TODO: change if it can be positioned correctly?
set_has_arrow: false,
}
}
}
}
let provider = gtk4::CssProvider::new();
provider.load_from_data(STYLE.as_bytes());
obj.style_context()
.add_provider(&provider, gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION);
self.menu_button.set(menu_button);
self.popover.set(popover);
self.panel_config
.set(CosmicPanelConfig::load_from_env().unwrap_or_default());
}
}
impl WidgetImpl for AppletInner {}
impl WindowImpl for AppletInner {}
glib::wrapper! {
pub struct Applet(ObjectSubclass<AppletInner>)
@extends gtk4::Widget, gtk4::Window;
}
impl Default for Applet {
fn default() -> Self {
Self::new()
}
}
impl Applet {
pub fn new() -> Self {
glib::Object::new(&[]).unwrap()
}
fn inner(&self) -> &AppletInner {
AppletInner::from_instance(self)
}
pub fn panel_config(&self) -> &CosmicPanelConfig {
&*self.inner().panel_config
}
pub fn set_button_child(&self, child: Option<&impl IsA<gtk4::Widget>>) {
self.inner().menu_button.set_child(child);
}
pub fn set_button_icon_name(&self, name: &str) {
let image = gtk4::Image::from_icon_name(name);
image.set_pixel_size(
self.panel_config()
.get_applet_icon_size()
.try_into()
.unwrap(),
); // XXX unwrap
self.set_button_child(Some(&image));
}
pub fn set_button_label(&self, label: &str) {
self.inner().menu_button.set_label(label);
}
pub fn set_popover_child(&self, child: Option<&impl IsA<gtk4::Widget>>) {
self.inner().popover.set_child(child);
}
}
// TODO also handle non-popover button? Is GtkMenuButton particularly special, or just use a toggle button?

View file

@ -0,0 +1,58 @@
use gtk4::{glib, prelude::*, subclass::prelude::*};
use relm4_macros::view;
static STYLE: &str = "
window.cosmic_applet_window {
background: transparent;
}
";
#[derive(Default)]
pub struct AppletWindowInner;
#[glib::object_subclass]
impl ObjectSubclass for AppletWindowInner {
const NAME: &'static str = "CosmicAppletWindow";
type Type = AppletWindow;
type ParentType = gtk4::Window;
}
impl ObjectImpl for AppletWindowInner {
fn constructed(&self, obj: &AppletWindow) {
let window = || obj;
view! {
window() {
add_css_class: "cosmic_applet_window",
set_decorated: false,
set_resizable: false,
set_width_request: 1,
set_height_request: 1,
},
provider = gtk4::CssProvider {
load_from_data: STYLE.as_bytes(),
}
}
obj.style_context()
.add_provider(&provider, gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION);
}
}
impl WidgetImpl for AppletWindowInner {}
impl WindowImpl for AppletWindowInner {}
glib::wrapper! {
pub struct AppletWindow(ObjectSubclass<AppletWindowInner>)
@extends gtk4::Widget, gtk4::Window;
}
impl Default for AppletWindow {
fn default() -> Self {
Self::new()
}
}
impl AppletWindow {
pub fn new() -> Self {
glib::Object::new(&[]).unwrap()
}
}