Compare commits
No commits in common. "bfe657faa016ccf747b16d2bcfcde6b6cd627894" and "bf630a4b572e937b56851cc1088e7563f64d0b34" have entirely different histories.
bfe657faa0
...
bf630a4b57
18 changed files with 751 additions and 1703 deletions
1668
Cargo.lock
generated
1668
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -80,15 +80,12 @@ cosmic-randr-shell = { workspace = true }
|
|||
kdl.workspace = true
|
||||
color-eyre.workspace = true
|
||||
image = { version = "0.25", default-features = false, features = [
|
||||
"avif-native",
|
||||
"jpeg",
|
||||
"png",
|
||||
"rayon",
|
||||
"webp",
|
||||
"hdr",
|
||||
] }
|
||||
# JPEG-XL support
|
||||
jxl-oxide = { version = "0.12.6", features = ["image"] }
|
||||
|
||||
[dependencies.greetd_ipc]
|
||||
version = "0.10.3"
|
||||
|
|
|
|||
1
debian/control
vendored
1
debian/control
vendored
|
|
@ -7,7 +7,6 @@ Build-Depends:
|
|||
git,
|
||||
just (>= 1.13.0),
|
||||
libclang-dev,
|
||||
libdav1d-dev,
|
||||
libinput-dev,
|
||||
libpam-dev,
|
||||
libwayland-dev,
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
cancel = Annuller
|
||||
restart = Genstart
|
||||
caps-lock = Skiftelås er aktiv.
|
||||
enter-user = Indtast navn manuelt...
|
||||
type-username = Brugernavn:
|
||||
keyboard-layout = Tastaturopsætning
|
||||
restart-now = Genstart nu?
|
||||
session = Session
|
||||
shutdown = Luk ned
|
||||
shutdown-now = Luk ned nu?
|
||||
user = Bruger
|
||||
suspend = Slumre
|
||||
auth-error-default = Godkendelse fejlede. Prøv venligst igen.
|
||||
auth-error-credentials = Ukorrekt adgangskode. Kontrollér venligst din tastaturopsætning og prøv igen.
|
||||
auth-error-denied = Adgang nægtet.
|
||||
auth-error-maxtries = For mange mislykkede godkendelsesforsøg.
|
||||
auth-error-account = Konto er utilgængelig eller deaktiveret.
|
||||
accessibility = Accessibility
|
||||
.screen-reader = Skærmlæser
|
||||
.magnifier = Forstørrelsesglas
|
||||
.high-contrast = Høj kontrast
|
||||
.invert-colors = Invertér Farver
|
||||
authenticating = Godkender...
|
||||
restart-timeout =
|
||||
The system will restart automatically
|
||||
{ $seconds ->
|
||||
[0] now.
|
||||
[1] in 1 second.
|
||||
*[other] in { $seconds } seconds.
|
||||
}
|
||||
shutdown-timeout =
|
||||
Systemet lukker automatisk ned
|
||||
{ $seconds ->
|
||||
[0] nu.
|
||||
[1] om 1 sekund.
|
||||
*[other] om { $seconds } sekunder.
|
||||
}
|
||||
|
|
@ -27,11 +27,11 @@ accessibility = Barrierefreiheit
|
|||
.magnifier = Vergrößerungsglas
|
||||
.high-contrast = Hoher Kontrast
|
||||
.invert-colors = Farben invertieren
|
||||
enter-user = Name manuell eingeben ...
|
||||
enter-user = Name manuell eingeben…
|
||||
type-username = Benutzername:
|
||||
auth-error-default = Authentifizierung fehlgeschlagen. Bitte versuche es erneut.
|
||||
auth-error-credentials = Falsches Passwort. Bitte überprüfe deine Tastaturbelegung und versuche es erneut.
|
||||
auth-error-denied = Zugriff verweigert.
|
||||
auth-error-maxtries = Zu viele fehlgeschlagene Authentifizierungsversuche.
|
||||
auth-error-account = Konto ist nicht verfügbar oder deaktiviert.
|
||||
authenticating = Authentifizierung ...
|
||||
authenticating = Authentifizierung...
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
cancel = Cancel
|
||||
|
|
@ -1 +0,0 @@
|
|||
cancel = لغو
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
cancel = Cancelar
|
||||
accessibility = Accesibilidade
|
||||
.screen-reader = Lector de pantalla
|
||||
.magnifier = Lupa
|
||||
.high-contrast = Alto contraste
|
||||
.invert-colors = Inverter cores
|
||||
authenticating = Autentificando...
|
||||
caps-lock = Bloqueo de Maiúsculas activo.
|
||||
enter-user = Introducir nome manualmente...
|
||||
type-username = Nome de usuario:
|
||||
keyboard-layout = Distribución do teclado
|
||||
restart = Reiniciar
|
||||
restart-now = Reiniciar agora?
|
||||
restart-timeout =
|
||||
O sistema reiniciarase automaticamente
|
||||
{ $seconds ->
|
||||
[0] agora.
|
||||
[1] dentro de 1 segundo.
|
||||
*[other] dentro de { $seconds } segundos.
|
||||
}
|
||||
session = Sesión
|
||||
shutdown = Apagar
|
||||
shutdown-now = Apagar agora?
|
||||
shutdown-timeout =
|
||||
O sistema apagarase automaticamente
|
||||
{ $seconds ->
|
||||
[0] agora.
|
||||
[1] dentro de 1 segundo.
|
||||
*[other] dentro de { $seconds } segundos.
|
||||
}
|
||||
suspend = Suspender
|
||||
user = Usuario
|
||||
auth-error-default = A autenticación fallou. Téntao de novo.
|
||||
auth-error-credentials = Contrasinal incorrecto. Comproba a distribución do teclado e téntao de novo.
|
||||
auth-error-denied = Acceso denegado.
|
||||
auth-error-maxtries = Demasiados intentos de autenticación.
|
||||
auth-error-account = A conta non estña dispoñible ou está deshabilitada.
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
shutdown = Atudar
|
||||
restart-timeout =
|
||||
Lo sistèma reaviarà automaticament
|
||||
{ $seconds ->
|
||||
[0] ara.
|
||||
[1] d’aquí 1 segondas.
|
||||
*[other] d’aquí { $seconds } segondas.
|
||||
}
|
||||
shutdown-timeout =
|
||||
Lo sistèma s'atudarà automaticament
|
||||
{ $seconds ->
|
||||
[0] ara.
|
||||
[1] d’aquí 1 segondas.
|
||||
*[other] d’aquí { $seconds } segondas.
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ shutdown-timeout =
|
|||
}
|
||||
suspend = Suspender
|
||||
user = Usuário
|
||||
authenticating = Autenticando...
|
||||
authenticating = Autenticando…
|
||||
auth-error-default = A autenticação falhou. Tente novamente.
|
||||
auth-error-credentials = Senha incorreta. Verifique o layout do seu teclado e tente novamente.
|
||||
auth-error-denied = Acesso negado.
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
cancel = ᱵᱟᱹᱛᱤᱞ
|
||||
157
src/common.rs
157
src/common.rs
|
|
@ -3,21 +3,14 @@ use cosmic::iced::core::SmolStr;
|
|||
use cosmic::iced::event::wayland::{Event as WaylandEvent, OutputEvent, SessionLockEvent};
|
||||
use cosmic::iced::event::{self};
|
||||
use cosmic::iced::keyboard::{Event as KeyEvent, Key, Modifiers};
|
||||
use cosmic::iced::platform_specific::shell::commands::blur::blur;
|
||||
use cosmic::iced::runtime::core::window::Id as SurfaceId;
|
||||
use cosmic::iced::runtime::platform_specific::wayland::CornerRadius;
|
||||
use cosmic::iced::{self, Rectangle, Size, Subscription};
|
||||
use cosmic::surface::corner_radius::rounded_rect_strips;
|
||||
use cosmic::widget::rectangle_tracker::{RectangleUpdate, rectangle_tracker_subscription};
|
||||
use cosmic::widget::{self, RectangleTracker};
|
||||
use cosmic_greeter_daemon::{BgSource, UserData};
|
||||
use cosmic_protocols::keyboard_layout::v1::client::zcosmic_keyboard_layout_v1::ZcosmicKeyboardLayoutV1;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use cosmic::widget;
|
||||
use cosmic_config::{ConfigSet, CosmicConfigEntry};
|
||||
use cosmic_greeter_daemon::{BgSource, CosmicCompConfig, UserData};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use wayland_client::protocol::wl_output::WlOutput;
|
||||
use wayland_client::{Connection, Proxy};
|
||||
|
||||
use crate::keyboard_layout_wayland;
|
||||
|
||||
pub const DEFAULT_MENU_ITEM_HEIGHT: f32 = 36.;
|
||||
|
||||
|
|
@ -29,15 +22,13 @@ pub struct ActiveLayout {
|
|||
}
|
||||
|
||||
pub struct Common<M> {
|
||||
pub wayland_connection: Option<Connection>,
|
||||
pub keyboard_layout: Option<ZcosmicKeyboardLayoutV1>,
|
||||
pub current_keyboard_layout: usize,
|
||||
pub active_layouts: Vec<ActiveLayout>,
|
||||
pub active_surface_id_opt: Option<SurfaceId>,
|
||||
pub on_battery: bool,
|
||||
pub battery_percent: f64,
|
||||
pub charging_limit: Option<bool>,
|
||||
pub caps_lock: bool,
|
||||
pub comp_config_handler: Option<cosmic_config::Config>,
|
||||
pub core: Core,
|
||||
pub error_opt: Option<String>,
|
||||
pub fallback_background: widget::image::Handle,
|
||||
|
|
@ -48,12 +39,8 @@ pub struct Common<M> {
|
|||
pub output_names: HashMap<WlOutput, String>,
|
||||
pub power_info_opt: Option<(widget::Icon, f64)>,
|
||||
pub prompt_opt: Option<(String, bool, Option<String>)>,
|
||||
pub rectangle_tracker: Option<RectangleTracker<(SurfaceId, bool)>>,
|
||||
pub rectangles: HashMap<(SurfaceId, bool), iced::Rectangle>,
|
||||
pub include_menu: bool,
|
||||
pub subsurface_rects: HashMap<WlOutput, Rectangle>,
|
||||
pub surface_ids: HashMap<WlOutput, SurfaceId>,
|
||||
pub subsurface_outputs: HashMap<SurfaceId, WlOutput>,
|
||||
pub surface_images: HashMap<SurfaceId, widget::image::Handle>,
|
||||
pub surface_names: HashMap<SurfaceId, String>,
|
||||
pub text_input_ids: HashMap<String, widget::Id>,
|
||||
|
|
@ -67,15 +54,12 @@ pub enum Message {
|
|||
Focus(SurfaceId),
|
||||
Key(Modifiers, Key, Option<SmolStr>),
|
||||
NetworkIcon(Option<&'static str>),
|
||||
SubsurfaceOpened(SurfaceId),
|
||||
OutputEvent(OutputEvent, WlOutput),
|
||||
PowerInfo(Option<(f64, bool, bool)>),
|
||||
Prompt(String, bool, Option<String>),
|
||||
SessionLockEvent(SessionLockEvent),
|
||||
Tick,
|
||||
Tz(jiff::tz::TimeZone),
|
||||
Rectangle(RectangleUpdate<(SurfaceId, bool)>),
|
||||
KeyboardLayoutWayland(keyboard_layout_wayland::Event),
|
||||
}
|
||||
|
||||
impl<M: From<Message> + Send + 'static> Common<M> {
|
||||
|
|
@ -88,6 +72,17 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
|||
core.window.show_minimize = false;
|
||||
core.window.use_template = false;
|
||||
|
||||
let comp_config_handler = match cosmic_config::Config::new(
|
||||
"com.system76.CosmicComp",
|
||||
CosmicCompConfig::VERSION,
|
||||
) {
|
||||
Ok(config_handler) => Some(config_handler),
|
||||
Err(err) => {
|
||||
tracing::error!("failed to create cosmic-comp config handler: {}", err);
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let layouts_opt = match xkb_data::all_keyboard_layouts() {
|
||||
Ok(ok) => Some(Arc::new(ok)),
|
||||
Err(err) => {
|
||||
|
|
@ -97,12 +92,10 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
|||
};
|
||||
|
||||
let app = Self {
|
||||
wayland_connection: None,
|
||||
keyboard_layout: None,
|
||||
current_keyboard_layout: 0,
|
||||
active_layouts: Vec::new(),
|
||||
active_surface_id_opt: None,
|
||||
caps_lock: false,
|
||||
comp_config_handler,
|
||||
core,
|
||||
error_opt: None,
|
||||
fallback_background: widget::image::Handle::from_bytes(
|
||||
|
|
@ -125,10 +118,6 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
|||
battery_percent: 0.0,
|
||||
on_battery: false,
|
||||
charging_limit: None,
|
||||
subsurface_outputs: HashMap::new(),
|
||||
rectangle_tracker: None,
|
||||
rectangles: HashMap::new(),
|
||||
include_menu: false,
|
||||
};
|
||||
(
|
||||
app,
|
||||
|
|
@ -139,6 +128,27 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn set_xkb_config(&self, user_data: &UserData) {
|
||||
if let Some(mut xkb_config) = user_data.xkb_config_opt.clone() {
|
||||
xkb_config.layout = String::new();
|
||||
xkb_config.variant = String::new();
|
||||
for (i, layout) in self.active_layouts.iter().enumerate() {
|
||||
if i > 0 {
|
||||
xkb_config.layout.push(',');
|
||||
xkb_config.variant.push(',');
|
||||
}
|
||||
xkb_config.layout.push_str(&layout.layout);
|
||||
xkb_config.variant.push_str(&layout.variant);
|
||||
}
|
||||
if let Some(comp_config_handler) = &self.comp_config_handler {
|
||||
match comp_config_handler.set("xkb_config", xkb_config) {
|
||||
Ok(()) => tracing::info!("updated cosmic-comp xkb_config"),
|
||||
Err(err) => tracing::error!("failed to update cosmic-comp xkb_config: {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_wallpapers(&mut self, user_data: &UserData) {
|
||||
for (_output, surface_id) in self.surface_ids.iter() {
|
||||
if self.surface_images.contains_key(surface_id) {
|
||||
|
|
@ -277,11 +287,6 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
|||
network_icon_opt.map(|name| widget::icon::from_name(name).into());
|
||||
}
|
||||
Message::OutputEvent(output_event, output) => {
|
||||
if self.wayland_connection.is_none() {
|
||||
if let Some(backend) = output.backend().upgrade() {
|
||||
self.wayland_connection = Some(Connection::from_backend(backend));
|
||||
}
|
||||
}
|
||||
if let Some(on_output_event) = &self.on_output_event {
|
||||
return Task::done(cosmic::Action::App(on_output_event(output_event, output)));
|
||||
}
|
||||
|
|
@ -317,88 +322,13 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
|||
Message::Tz(tz) => {
|
||||
self.time.set_tz(tz);
|
||||
}
|
||||
Message::SubsurfaceOpened(id) => {
|
||||
return self.blur_rects(id);
|
||||
}
|
||||
Message::Rectangle(u) => match u {
|
||||
RectangleUpdate::Rectangle(r) => {
|
||||
self.rectangles.insert(r.0, r.1);
|
||||
|
||||
return self.blur_rects(r.0.0);
|
||||
}
|
||||
RectangleUpdate::Init(tracker) => {
|
||||
self.rectangle_tracker.replace(tracker);
|
||||
}
|
||||
},
|
||||
Message::KeyboardLayoutWayland(w) => match w {
|
||||
keyboard_layout_wayland::Event::KeyboardLayout(keyboard_layout) => {
|
||||
self.keyboard_layout = Some(keyboard_layout);
|
||||
}
|
||||
keyboard_layout_wayland::Event::Group(group) => {
|
||||
self.current_keyboard_layout = group;
|
||||
}
|
||||
},
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
pub(crate) fn dropdown_blur_rects(&mut self, enable: bool) -> Task<M> {
|
||||
let mut ids = HashSet::new();
|
||||
for r in self.rectangles.keys() {
|
||||
ids.insert(r.0);
|
||||
}
|
||||
self.include_menu = enable;
|
||||
Task::batch(
|
||||
ids.into_iter()
|
||||
.map(|i| self.blur_rects(i))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn blur_rects(&mut self, id: SurfaceId) -> Task<M> {
|
||||
if let Some(output) = self.subsurface_outputs.get(&id) {
|
||||
if let Some(rect) = self.subsurface_rects.get(output) {
|
||||
let x = rect.x;
|
||||
let y = rect.y;
|
||||
if let Some(rect) = self.rectangles.get(&(id, false)) {
|
||||
let mut offset_rect = *rect;
|
||||
offset_rect.x += x;
|
||||
offset_rect.y += y;
|
||||
let rad = CornerRadius {
|
||||
top_left: 16,
|
||||
top_right: 16,
|
||||
bottom_left: 16,
|
||||
bottom_right: 16,
|
||||
};
|
||||
let mut rects = rounded_rect_strips(offset_rect, rad);
|
||||
if let Some(other_rect) = self.rectangles.get(&(id, true))
|
||||
&& self.include_menu
|
||||
{
|
||||
let mut other = *other_rect;
|
||||
other.x += x;
|
||||
other.y += y;
|
||||
let rad = CornerRadius {
|
||||
top_left: 8,
|
||||
top_right: 8,
|
||||
bottom_left: 8,
|
||||
bottom_right: 8,
|
||||
};
|
||||
rects.append(&mut rounded_rect_strips(other, rad));
|
||||
}
|
||||
|
||||
return blur(id, Some(rects)).discard();
|
||||
} else {
|
||||
tracing::error!("no rectangle for surface {id:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
pub fn subscription(&self) -> Subscription<Message> {
|
||||
let mut subscriptions = Vec::with_capacity(3);
|
||||
subscriptions
|
||||
.push(rectangle_tracker_subscription(0).map(|update| Message::Rectangle(update.1)));
|
||||
|
||||
subscriptions.push(event::listen_with(|event, status, id| match event {
|
||||
iced::Event::Keyboard(KeyEvent::KeyPressed {
|
||||
key,
|
||||
|
|
@ -421,21 +351,12 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
|||
WaylandEvent::SessionLock(lock_event) => {
|
||||
Some(Message::SessionLockEvent(lock_event))
|
||||
}
|
||||
iced::event::wayland::Event::Subsurface(
|
||||
iced::event::wayland::SubsurfaceEvent::Created,
|
||||
) => Some(Message::SubsurfaceOpened(id)),
|
||||
_ => None,
|
||||
},
|
||||
iced::Event::Window(iced::window::Event::Focused) => Some(Message::Focus(id)),
|
||||
_ => None,
|
||||
}));
|
||||
|
||||
if let Some(conn) = self.wayland_connection.clone() {
|
||||
subscriptions.push(
|
||||
keyboard_layout_wayland::subscription(conn).map(Message::KeyboardLayoutWayland),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "networkmanager")]
|
||||
{
|
||||
subscriptions.push(crate::networkmanager::subscription().map(Message::NetworkIcon));
|
||||
|
|
|
|||
186
src/greeter.rs
186
src/greeter.rs
|
|
@ -24,8 +24,7 @@ use cosmic::iced::platform_specific::shell::wayland::commands::subsurface::repos
|
|||
use cosmic::iced::runtime::core::window::Id as SurfaceId;
|
||||
use cosmic::iced::runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings;
|
||||
use cosmic::iced::{
|
||||
self, Alignment, Background, Border, Color, Length, Point, Rectangle, Size, Subscription,
|
||||
window,
|
||||
self, Alignment, Background, Border, Length, Point, Size, Subscription, window,
|
||||
};
|
||||
use cosmic::widget::{id_container, text};
|
||||
use cosmic::{Element, executor, surface, theme, widget};
|
||||
|
|
@ -280,8 +279,6 @@ pub fn main() -> Result<(), Box<dyn Error>> {
|
|||
sessions
|
||||
};
|
||||
|
||||
let logind_available = cfg!(feature = "logind") && crate::logind::is_available();
|
||||
|
||||
let flags = Flags {
|
||||
user_icons: user_datas
|
||||
.iter_mut()
|
||||
|
|
@ -291,7 +288,6 @@ pub fn main() -> Result<(), Box<dyn Error>> {
|
|||
sessions,
|
||||
greeter_config,
|
||||
greeter_config_handler,
|
||||
logind_available,
|
||||
};
|
||||
|
||||
let settings = Settings::default().no_main_window(true);
|
||||
|
|
@ -308,7 +304,6 @@ pub struct Flags {
|
|||
sessions: HashMap<String, (Vec<String>, Vec<String>)>,
|
||||
greeter_config: CosmicGreeterConfig,
|
||||
greeter_config_handler: Option<cosmic_config::Config>,
|
||||
logind_available: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -542,7 +537,7 @@ impl App {
|
|||
let dropdown_menu = |items: Vec<_>| {
|
||||
let item_cnt = items.len();
|
||||
|
||||
let items = widget::menu::menu_column::MenuColumn::with_children(items);
|
||||
let items = widget::column::with_children(items);
|
||||
let items = if item_cnt > 7 {
|
||||
Element::from(
|
||||
widget::scrollable(items)
|
||||
|
|
@ -552,12 +547,12 @@ impl App {
|
|||
Element::from(items)
|
||||
};
|
||||
|
||||
let menu = widget::container(items)
|
||||
widget::container(items)
|
||||
.padding(1)
|
||||
//TODO: move style to libcosmic
|
||||
.class(theme::Container::custom(|theme| {
|
||||
let cosmic = theme.cosmic();
|
||||
let component = &cosmic.background(theme.transparent).component;
|
||||
let component = &cosmic.background(false).component;
|
||||
widget::container::Style {
|
||||
icon_color: Some(component.on.into()),
|
||||
text_color: Some(component.on.into()),
|
||||
|
|
@ -570,13 +565,7 @@ impl App {
|
|||
..Default::default()
|
||||
}
|
||||
}))
|
||||
.width(Length::Fixed(240.0));
|
||||
|
||||
if let Some(t) = self.common.rectangle_tracker.as_ref() {
|
||||
Element::from(t.container((id, true), menu))
|
||||
} else {
|
||||
menu.into()
|
||||
}
|
||||
.width(Length::Fixed(240.0))
|
||||
};
|
||||
|
||||
let mut input_button = widget::popover(
|
||||
|
|
@ -590,7 +579,7 @@ impl App {
|
|||
for (i, layout) in self.common.active_layouts.iter().enumerate() {
|
||||
items.push(menu_checklist(
|
||||
&layout.description,
|
||||
i == self.common.current_keyboard_layout,
|
||||
i == 0,
|
||||
Message::KeyboardLayout(i),
|
||||
));
|
||||
}
|
||||
|
|
@ -692,7 +681,7 @@ impl App {
|
|||
|
||||
let accessibility_button = accessibility_dropdown;
|
||||
|
||||
let mut button_row = iced::widget::row![
|
||||
let button_row = iced::widget::row![
|
||||
widget::tooltip(
|
||||
accessibility_button,
|
||||
text(fl!("accessibility")),
|
||||
|
|
@ -713,32 +702,30 @@ impl App {
|
|||
text(fl!("session")),
|
||||
widget::tooltip::Position::Top
|
||||
),
|
||||
];
|
||||
if self.flags.logind_available {
|
||||
button_row = button_row
|
||||
.push(widget::tooltip(
|
||||
widget::button::custom(widget::icon::from_name("system-suspend-symbolic"))
|
||||
.padding(12.0)
|
||||
.on_press(Message::Suspend),
|
||||
text(fl!("suspend")),
|
||||
widget::tooltip::Position::Top,
|
||||
))
|
||||
.push(widget::tooltip(
|
||||
widget::button::custom(widget::icon::from_name("system-reboot-symbolic"))
|
||||
.padding(12.0)
|
||||
.on_press(Message::Restart),
|
||||
text(fl!("restart")),
|
||||
widget::tooltip::Position::Top,
|
||||
))
|
||||
.push(widget::tooltip(
|
||||
widget::button::custom(widget::icon::from_name("system-shutdown-symbolic"))
|
||||
.padding(12.0)
|
||||
.on_press(Message::Shutdown),
|
||||
text(fl!("shutdown")),
|
||||
widget::tooltip::Position::Top,
|
||||
));
|
||||
}
|
||||
let button_row = button_row.padding([16.0, 0.0, 0.0, 0.0]).spacing(8.0);
|
||||
widget::tooltip(
|
||||
widget::button::custom(widget::icon::from_name("system-suspend-symbolic"))
|
||||
.padding(12.0)
|
||||
.on_press(Message::Suspend),
|
||||
text(fl!("suspend")),
|
||||
widget::tooltip::Position::Top
|
||||
),
|
||||
widget::tooltip(
|
||||
widget::button::custom(widget::icon::from_name("system-reboot-symbolic"))
|
||||
.padding(12.0)
|
||||
.on_press(Message::Restart),
|
||||
text(fl!("restart")),
|
||||
widget::tooltip::Position::Top
|
||||
),
|
||||
widget::tooltip(
|
||||
widget::button::custom(widget::icon::from_name("system-shutdown-symbolic"))
|
||||
.padding(12.0)
|
||||
.on_press(Message::Shutdown),
|
||||
text(fl!("shutdown")),
|
||||
widget::tooltip::Position::Top
|
||||
)
|
||||
]
|
||||
.padding([16.0, 0.0, 0.0, 0.0])
|
||||
.spacing(8.0);
|
||||
|
||||
widget::container(iced::widget::column![
|
||||
date_time_column,
|
||||
|
|
@ -941,37 +928,29 @@ impl App {
|
|||
},
|
||||
)
|
||||
};
|
||||
|
||||
let menu = widget::layer_container(
|
||||
iced::widget::row![left_element, right_element].align_y(Alignment::Start),
|
||||
)
|
||||
.layer(cosmic::cosmic_theme::Layer::Background)
|
||||
.padding(16)
|
||||
.class(cosmic::theme::Container::Custom(Box::new(
|
||||
|theme: &cosmic::Theme| {
|
||||
// Use background appearance as the base
|
||||
let mut appearance =
|
||||
widget::container::Catalog::style(theme, &cosmic::theme::Container::Background);
|
||||
appearance.background = Some(iced::Background::Color(
|
||||
// TODO if we can use popups instead of subsurfaces for the greeter and the lockscreen
|
||||
// then we can allow transparency
|
||||
theme.cosmic().background(theme.transparent).base.into(),
|
||||
));
|
||||
appearance.border = iced::Border::default().rounded(16);
|
||||
appearance
|
||||
},
|
||||
)))
|
||||
.width(Length::Fixed(800.0));
|
||||
let menu = if let Some(t) = self.common.rectangle_tracker.as_ref() {
|
||||
Element::from(t.container((id, false), menu))
|
||||
} else {
|
||||
menu.into()
|
||||
};
|
||||
let menu = widget::container(widget::column::with_children(vec![
|
||||
widget::space::vertical()
|
||||
.height(Length::FillPortion(1))
|
||||
.into(),
|
||||
menu,
|
||||
widget::layer_container(
|
||||
iced::widget::row![left_element, right_element].align_y(Alignment::Start),
|
||||
)
|
||||
.layer(cosmic::cosmic_theme::Layer::Background)
|
||||
.padding(16)
|
||||
.class(cosmic::theme::Container::Custom(Box::new(
|
||||
|theme: &cosmic::Theme| {
|
||||
// Use background appearance as the base
|
||||
let mut appearance = widget::container::Catalog::style(
|
||||
theme,
|
||||
&cosmic::theme::Container::Background,
|
||||
);
|
||||
appearance.border = iced::Border::default().rounded(16);
|
||||
appearance
|
||||
},
|
||||
)))
|
||||
.class(cosmic::theme::Container::Background)
|
||||
.width(Length::Fixed(800.0))
|
||||
.into(),
|
||||
widget::space::vertical()
|
||||
.height(Length::FillPortion(4))
|
||||
.into(),
|
||||
|
|
@ -980,7 +959,6 @@ impl App {
|
|||
.height(Length::Fill)
|
||||
.align_x(Alignment::Center);
|
||||
|
||||
// TODO make these opaque?
|
||||
let popover = widget::popover(menu).modal(true);
|
||||
match self.dialog_page_opt {
|
||||
Some(DialogPage::Restart(instant)) => {
|
||||
|
|
@ -1035,6 +1013,19 @@ impl App {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_xkb_config(&self) {
|
||||
let user_data = match self
|
||||
.selected_username
|
||||
.data_idx
|
||||
.and_then(|i| self.flags.user_datas.get(i))
|
||||
{
|
||||
Some(some) => some,
|
||||
None => return,
|
||||
};
|
||||
|
||||
self.common.set_xkb_config(user_data);
|
||||
}
|
||||
|
||||
fn update_user_data(&mut self) -> Task<Message> {
|
||||
let user_data = match self
|
||||
.selected_username
|
||||
|
|
@ -1049,6 +1040,9 @@ impl App {
|
|||
|
||||
self.common.update_user_data(user_data);
|
||||
|
||||
// Ensure that user's xkb config is used
|
||||
self.common.set_xkb_config(user_data);
|
||||
|
||||
if let Some(builder) = &user_data.theme_builder_opt {
|
||||
self.theme_builder = builder.clone();
|
||||
}
|
||||
|
|
@ -1096,8 +1090,7 @@ impl cosmic::Application for App {
|
|||
}
|
||||
|
||||
/// Creates the application, and optionally emits command on initialize.
|
||||
fn init(mut core: Core, flags: Self::Flags) -> (Self, Task<Message>) {
|
||||
core.set_app_type(cosmic::core::AppType::System);
|
||||
fn init(core: Core, flags: Self::Flags) -> (Self, Task<Message>) {
|
||||
let mut tasks = Vec::new();
|
||||
let (mut common, common_task) = Common::init(core);
|
||||
common.on_output_event = Some(Box::new(|output_event, output| {
|
||||
|
|
@ -1258,12 +1251,7 @@ impl cosmic::Application for App {
|
|||
surface_id,
|
||||
Size::new(unwrapped_size.0 as f32, unwrapped_size.1 as f32),
|
||||
);
|
||||
self.common
|
||||
.subsurface_rects
|
||||
.insert(output.clone(), Rectangle::new(loc, sub_size));
|
||||
self.common
|
||||
.subsurface_outputs
|
||||
.insert(subsurface_id, output.clone());
|
||||
|
||||
let msg = cosmic::surface::action::subsurface(
|
||||
move |_: &mut App| SctkSubsurfaceSettings {
|
||||
parent: surface_id,
|
||||
|
|
@ -1342,7 +1330,6 @@ impl cosmic::Application for App {
|
|||
self.selected_session = selected_session;
|
||||
if self.dropdown_opt == Some(Dropdown::Session) {
|
||||
self.dropdown_opt = None;
|
||||
return self.common.dropdown_blur_rects(false);
|
||||
}
|
||||
}
|
||||
Message::EnterUser(focus_input, username) => {
|
||||
|
|
@ -1359,10 +1346,7 @@ impl cosmic::Application for App {
|
|||
username,
|
||||
};
|
||||
if focus_input {
|
||||
return Task::batch([
|
||||
self.common.dropdown_blur_rects(false),
|
||||
widget::text_input::focus(USERNAME_ID.clone()),
|
||||
]);
|
||||
return widget::text_input::focus(USERNAME_ID.clone());
|
||||
}
|
||||
}
|
||||
Message::Username(username) => {
|
||||
|
|
@ -1400,12 +1384,9 @@ impl cosmic::Application for App {
|
|||
self.send_request(Request::CancelSession);
|
||||
}
|
||||
if let Some(randr_list) = self.randr_list.as_ref() {
|
||||
return Task::batch([
|
||||
self.common.dropdown_blur_rects(false),
|
||||
self.update(Message::RandrUpdate {
|
||||
randr: Arc::new(Ok(randr_list.clone())),
|
||||
}),
|
||||
]);
|
||||
return self.update(Message::RandrUpdate {
|
||||
randr: Arc::new(Ok(randr_list.clone())),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1486,9 +1467,6 @@ impl cosmic::Application for App {
|
|||
}
|
||||
}
|
||||
Message::Auth(response) => {
|
||||
if response.as_deref() == Some("") {
|
||||
return Task::none();
|
||||
}
|
||||
self.common.error_opt = None;
|
||||
self.authenticating = true;
|
||||
self.send_request(Request::PostAuthMessageResponse { response });
|
||||
|
|
@ -1520,9 +1498,6 @@ impl cosmic::Application for App {
|
|||
if let Some(handle) = self.heartbeat_handle.take() {
|
||||
handle.abort();
|
||||
}
|
||||
if self.dropdown_opt.is_some() {
|
||||
return self.common.dropdown_blur_rects(true);
|
||||
}
|
||||
}
|
||||
Message::DialogConfirm => match self.dialog_page_opt.take() {
|
||||
Some(DialogPage::Restart(_)) => {
|
||||
|
|
@ -1549,26 +1524,20 @@ impl cosmic::Application for App {
|
|||
})
|
||||
.discard();
|
||||
}
|
||||
None => {
|
||||
if self.dropdown_opt.is_some() {
|
||||
return self.common.dropdown_blur_rects(true);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
},
|
||||
Message::DropdownToggle(dropdown) => {
|
||||
if self.dropdown_opt == Some(dropdown) {
|
||||
self.dropdown_opt = None;
|
||||
return self.common.dropdown_blur_rects(false);
|
||||
} else {
|
||||
self.dropdown_opt = Some(dropdown);
|
||||
return self.common.dropdown_blur_rects(true);
|
||||
}
|
||||
}
|
||||
Message::KeyboardLayout(layout_i) => {
|
||||
if let Some(keyboard_layout) = &self.common.keyboard_layout {
|
||||
keyboard_layout.set_group(layout_i as u32);
|
||||
if layout_i < self.common.active_layouts.len() {
|
||||
self.common.active_layouts.swap(0, layout_i);
|
||||
self.set_xkb_config();
|
||||
}
|
||||
self.common.current_keyboard_layout = layout_i;
|
||||
if self.dropdown_opt == Some(Dropdown::Keyboard) {
|
||||
self.dropdown_opt = None
|
||||
}
|
||||
|
|
@ -1614,8 +1583,7 @@ impl cosmic::Application for App {
|
|||
.abortable();
|
||||
|
||||
self.heartbeat_handle = Some(handle);
|
||||
self.common.include_menu = false;
|
||||
return Task::batch(vec![self.common.dropdown_blur_rects(false), heartbeat]);
|
||||
return heartbeat;
|
||||
}
|
||||
}
|
||||
Message::Heartbeat => match self.dialog_page_opt {
|
||||
|
|
|
|||
|
|
@ -1,157 +0,0 @@
|
|||
use cctk::{
|
||||
cosmic_protocols::keyboard_layout::v1::client::zcosmic_keyboard_layout_v1::ZcosmicKeyboardLayoutV1,
|
||||
keyboard_layout::{KeyboardLayoutHandler, KeyboardLayoutState},
|
||||
sctk::{
|
||||
self,
|
||||
registry::{ProvidesRegistryState, RegistryState},
|
||||
seat::{Capability, SeatHandler, SeatState},
|
||||
},
|
||||
wayland_client::{
|
||||
Connection, QueueHandle, delegate_noop,
|
||||
globals::registry_queue_init,
|
||||
protocol::{wl_keyboard, wl_seat},
|
||||
},
|
||||
};
|
||||
use cosmic::iced;
|
||||
use cosmic::iced::futures::{SinkExt, channel::mpsc, executor::block_on};
|
||||
use std::{hash::Hash, thread};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Event {
|
||||
KeyboardLayout(ZcosmicKeyboardLayoutV1),
|
||||
Group(usize),
|
||||
}
|
||||
|
||||
pub fn subscription(connection: Connection) -> iced::Subscription<Event> {
|
||||
#[derive(Clone)]
|
||||
struct WaylandSubscription(Connection);
|
||||
impl Hash for WaylandSubscription {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.backend().display_id().hash(state);
|
||||
}
|
||||
}
|
||||
iced::Subscription::run_with(
|
||||
WaylandSubscription(connection),
|
||||
|WaylandSubscription(connection)| {
|
||||
let connection = connection.clone();
|
||||
iced::stream::channel(8, move |sender| async move {
|
||||
thread::spawn(move || thread(connection, sender));
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
struct Keyboard {
|
||||
seat: wl_seat::WlSeat,
|
||||
keyboard_layout: ZcosmicKeyboardLayoutV1,
|
||||
}
|
||||
|
||||
impl Drop for Keyboard {
|
||||
fn drop(&mut self) {
|
||||
self.keyboard_layout.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
struct AppData {
|
||||
seat_state: SeatState,
|
||||
registry_state: RegistryState,
|
||||
keyboard_layout_state: KeyboardLayoutState,
|
||||
keyboard: Option<Keyboard>,
|
||||
sender: mpsc::Sender<Event>,
|
||||
}
|
||||
|
||||
impl KeyboardLayoutHandler for AppData {
|
||||
fn group(
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
_keyboard: &wl_keyboard::WlKeyboard,
|
||||
_keyboard_layout: &ZcosmicKeyboardLayoutV1,
|
||||
group: u32,
|
||||
) {
|
||||
let _ = block_on(self.sender.send(Event::Group(group as usize)));
|
||||
}
|
||||
}
|
||||
|
||||
impl ProvidesRegistryState for AppData {
|
||||
fn registry(&mut self) -> &mut RegistryState {
|
||||
&mut self.registry_state
|
||||
}
|
||||
|
||||
sctk::registry_handlers![SeatState,];
|
||||
}
|
||||
|
||||
impl SeatHandler for AppData {
|
||||
fn seat_state(&mut self) -> &mut SeatState {
|
||||
&mut self.seat_state
|
||||
}
|
||||
|
||||
fn new_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, _: wl_seat::WlSeat) {}
|
||||
|
||||
fn new_capability(
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
qh: &QueueHandle<Self>,
|
||||
seat: wl_seat::WlSeat,
|
||||
capability: Capability,
|
||||
) {
|
||||
if capability == Capability::Keyboard && self.keyboard.is_none() {
|
||||
let keyboard = seat.get_keyboard(qh, ());
|
||||
let keyboard_layout = self
|
||||
.keyboard_layout_state
|
||||
.get_keyboard_layout(&keyboard, qh);
|
||||
keyboard.release();
|
||||
|
||||
if let Some(keyboard_layout) = keyboard_layout {
|
||||
let _ = block_on(
|
||||
self.sender
|
||||
.send(Event::KeyboardLayout(keyboard_layout.clone())),
|
||||
);
|
||||
self.keyboard = Some(Keyboard {
|
||||
seat,
|
||||
keyboard_layout,
|
||||
});
|
||||
} else {
|
||||
keyboard.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_capability(
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
_: &QueueHandle<Self>,
|
||||
seat: wl_seat::WlSeat,
|
||||
_capability: Capability,
|
||||
) {
|
||||
self.keyboard.take_if(|x| x.seat == seat);
|
||||
}
|
||||
|
||||
fn remove_seat(&mut self, _: &Connection, _: &QueueHandle<Self>, seat: wl_seat::WlSeat) {
|
||||
self.keyboard.take_if(|x| x.seat == seat);
|
||||
}
|
||||
}
|
||||
|
||||
fn thread(conn: Connection, sender: mpsc::Sender<Event>) {
|
||||
let (globals, mut event_queue) = registry_queue_init(&conn).unwrap();
|
||||
let qh = event_queue.handle();
|
||||
let registry_state = RegistryState::new(&globals);
|
||||
let seat_state = SeatState::new(&globals, &qh);
|
||||
let keyboard_layout_state = KeyboardLayoutState::new(®istry_state, &qh);
|
||||
|
||||
let mut app_data = AppData {
|
||||
seat_state,
|
||||
registry_state,
|
||||
keyboard_layout_state,
|
||||
keyboard: None,
|
||||
sender,
|
||||
};
|
||||
loop {
|
||||
event_queue.blocking_dispatch(&mut app_data).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
sctk::delegate_registry!(AppData);
|
||||
sctk::delegate_seat!(AppData);
|
||||
cctk::delegate_keyboard_layout!(AppData);
|
||||
delegate_noop!(AppData: ignore wl_keyboard::WlKeyboard);
|
||||
|
|
@ -8,8 +8,6 @@ mod wayland;
|
|||
|
||||
mod common;
|
||||
|
||||
mod keyboard_layout_wayland;
|
||||
|
||||
mod localize;
|
||||
|
||||
#[cfg(feature = "logind")]
|
||||
|
|
|
|||
158
src/locker.rs
158
src/locker.rs
|
|
@ -79,8 +79,6 @@ pub fn main(user: pwd::Passwd) -> Result<(), Box<dyn std::error::Error>> {
|
|||
// We are already the user at this point
|
||||
user_data.load_config_as_user();
|
||||
|
||||
let logind_available = cfg!(feature = "logind") && crate::logind::is_available();
|
||||
|
||||
let flags = Flags {
|
||||
user_icon: user_data
|
||||
.icon_opt
|
||||
|
|
@ -88,7 +86,6 @@ pub fn main(user: pwd::Passwd) -> Result<(), Box<dyn std::error::Error>> {
|
|||
.map(widget::image::Handle::from_bytes),
|
||||
user_data,
|
||||
lockfile_opt: lockfile_opt(),
|
||||
logind_available,
|
||||
};
|
||||
|
||||
let settings = Settings::default().no_main_window(true);
|
||||
|
|
@ -250,7 +247,6 @@ pub struct Flags {
|
|||
user_data: UserData,
|
||||
user_icon: Option<widget::image::Handle>,
|
||||
lockfile_opt: Option<PathBuf>,
|
||||
logind_available: bool,
|
||||
}
|
||||
|
||||
///TODO: this is custom code that should be better handled by libcosmic
|
||||
|
|
@ -376,7 +372,7 @@ impl App {
|
|||
let dropdown_menu = |items: Vec<_>| {
|
||||
let item_cnt = items.len();
|
||||
|
||||
let items = widget::menu::menu_column::MenuColumn::with_children(items);
|
||||
let items = widget::column::with_children(items);
|
||||
let items = if item_cnt > 7 {
|
||||
Element::from(
|
||||
widget::scrollable(items)
|
||||
|
|
@ -386,32 +382,25 @@ impl App {
|
|||
Element::from(items)
|
||||
};
|
||||
|
||||
let menu: widget::Container<'_, Message, cosmic::prelude::Theme> =
|
||||
widget::container(items)
|
||||
.padding(1)
|
||||
//TODO: move style to libcosmic
|
||||
.class(theme::Container::custom(|theme| {
|
||||
let cosmic = theme.cosmic();
|
||||
let component = &cosmic.background(theme.transparent).component;
|
||||
widget::container::Style {
|
||||
icon_color: Some(component.on.into()),
|
||||
text_color: Some(component.on.into()),
|
||||
background: Some(Background::Color(component.base.into())),
|
||||
border: Border {
|
||||
radius: 8.0.into(),
|
||||
width: 1.0,
|
||||
color: component.divider.into(),
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
}))
|
||||
.width(Length::Fixed(240.0));
|
||||
|
||||
if let Some(t) = self.common.rectangle_tracker.as_ref() {
|
||||
Element::from(t.container((surface_id, true), menu))
|
||||
} else {
|
||||
menu.into()
|
||||
}
|
||||
widget::container(items)
|
||||
.padding(1)
|
||||
//TODO: move style to libcosmic
|
||||
.class(theme::Container::custom(|theme| {
|
||||
let cosmic = theme.cosmic();
|
||||
let component = &cosmic.background(false).component;
|
||||
widget::container::Style {
|
||||
icon_color: Some(component.on.into()),
|
||||
text_color: Some(component.on.into()),
|
||||
background: Some(Background::Color(component.base.into())),
|
||||
border: Border {
|
||||
radius: 8.0.into(),
|
||||
width: 1.0,
|
||||
color: component.divider.into(),
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
}))
|
||||
.width(Length::Fixed(240.0))
|
||||
};
|
||||
|
||||
let mut input_button = widget::popover(
|
||||
|
|
@ -425,7 +414,7 @@ impl App {
|
|||
for (i, layout) in self.common.active_layouts.iter().enumerate() {
|
||||
items.push(menu_checklist(
|
||||
&layout.description,
|
||||
i == self.common.current_keyboard_layout,
|
||||
i == 0,
|
||||
Message::KeyboardLayout(i),
|
||||
));
|
||||
}
|
||||
|
|
@ -433,7 +422,7 @@ impl App {
|
|||
}
|
||||
|
||||
//TODO: implement these buttons
|
||||
let mut button_row = iced::widget::row![
|
||||
let button_row = iced::widget::row![
|
||||
/*TODO: greeter accessibility options
|
||||
widget::button::custom(widget::icon::from_name(
|
||||
"applications-accessibility-symbolic"
|
||||
|
|
@ -446,17 +435,16 @@ impl App {
|
|||
widget::text(fl!("keyboard-layout")),
|
||||
widget::tooltip::Position::Top
|
||||
),
|
||||
];
|
||||
if cfg!(feature = "logind") && self.flags.logind_available {
|
||||
button_row = button_row.push(widget::tooltip(
|
||||
widget::tooltip(
|
||||
widget::button::custom(widget::icon::from_name("system-suspend-symbolic"))
|
||||
.padding(12.0)
|
||||
.on_press(Message::Suspend),
|
||||
widget::text(fl!("suspend")),
|
||||
widget::tooltip::Position::Top,
|
||||
));
|
||||
}
|
||||
let button_row = button_row.padding([16.0, 0.0, 0.0, 0.0]).spacing(8.0);
|
||||
widget::tooltip::Position::Top
|
||||
),
|
||||
]
|
||||
.padding([16.0, 0.0, 0.0, 0.0])
|
||||
.spacing(8.0);
|
||||
|
||||
widget::container(iced::widget::column![
|
||||
date_time_column,
|
||||
|
|
@ -597,34 +585,30 @@ impl App {
|
|||
.align_x(Alignment::Center)
|
||||
.width(Length::Fill)
|
||||
};
|
||||
let menu = widget::layer_container(
|
||||
iced::widget::row![left_element, right_element].align_y(Alignment::Start),
|
||||
)
|
||||
.layer(cosmic::cosmic_theme::Layer::Background)
|
||||
.padding(16)
|
||||
.class(cosmic::theme::Container::Custom(Box::new(
|
||||
|theme: &cosmic::Theme| {
|
||||
// Use background appearance as the base
|
||||
let mut appearance =
|
||||
widget::container::Catalog::style(theme, &cosmic::theme::Container::Background);
|
||||
let c: iced::Color = theme.cosmic().background(theme.transparent).base.into();
|
||||
appearance.background = Some(iced::Background::Color(c));
|
||||
appearance.border = iced::Border::default().rounded(16.0);
|
||||
appearance
|
||||
},
|
||||
)))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Shrink);
|
||||
let menu = if let Some(t) = self.common.rectangle_tracker.as_ref() {
|
||||
Element::from(t.container((surface_id, false), menu))
|
||||
} else {
|
||||
menu.into()
|
||||
};
|
||||
|
||||
widget::container(widget::column::with_children(vec![
|
||||
widget::space::vertical()
|
||||
.height(Length::FillPortion(1))
|
||||
.into(),
|
||||
menu,
|
||||
widget::layer_container(
|
||||
iced::widget::row![left_element, right_element].align_y(Alignment::Start),
|
||||
)
|
||||
.layer(cosmic::cosmic_theme::Layer::Background)
|
||||
.padding(16)
|
||||
.class(cosmic::theme::Container::Custom(Box::new(
|
||||
|theme: &cosmic::Theme| {
|
||||
// Use background appearance as the base
|
||||
let mut appearance = widget::container::Catalog::style(
|
||||
theme,
|
||||
&cosmic::theme::Container::Background,
|
||||
);
|
||||
appearance.border = iced::Border::default().rounded(16.0);
|
||||
appearance
|
||||
},
|
||||
)))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Shrink)
|
||||
.into(),
|
||||
widget::space::vertical()
|
||||
.height(Length::FillPortion(4))
|
||||
.into(),
|
||||
|
|
@ -660,8 +644,7 @@ impl cosmic::Application for App {
|
|||
}
|
||||
|
||||
/// Creates the application, and optionally emits command on initialize.
|
||||
fn init(mut core: Core, flags: Self::Flags) -> (Self, Task<Self::Message>) {
|
||||
core.set_app_type(cosmic::core::AppType::System);
|
||||
fn init(core: Core, flags: Self::Flags) -> (Self, Task<Self::Message>) {
|
||||
let (mut common, common_task) = Common::init(core);
|
||||
common.on_output_event = Some(Box::new(|output_event, output| {
|
||||
Message::OutputEvent(output_event, output)
|
||||
|
|
@ -684,18 +667,18 @@ impl cosmic::Application for App {
|
|||
authenticating: false,
|
||||
};
|
||||
|
||||
let task = if cfg!(feature = "logind") && app.flags.logind_available {
|
||||
let task = if cfg!(feature = "logind") {
|
||||
if already_locked {
|
||||
// Recover previously locked state
|
||||
tracing::info!("recovering previous locked state");
|
||||
app.state = State::Locking;
|
||||
lock()
|
||||
} else {
|
||||
// When logind is available, wait for lock signal
|
||||
// When logind feature is used, wait for lock signal
|
||||
Task::none()
|
||||
}
|
||||
} else {
|
||||
// When logind is not available, lock immediately
|
||||
// When logind feature not used, lock immediately
|
||||
tracing::info!("locking immediately");
|
||||
app.state = State::Locking;
|
||||
lock()
|
||||
|
|
@ -731,10 +714,6 @@ impl cosmic::Application for App {
|
|||
return Task::none();
|
||||
}
|
||||
|
||||
self.common
|
||||
.subsurface_outputs
|
||||
.insert(subsurface_id, output.clone());
|
||||
|
||||
let size = if let Some((w, h)) =
|
||||
output_info_opt.as_ref().and_then(|info| info.logical_size)
|
||||
{
|
||||
|
|
@ -812,11 +791,11 @@ impl cosmic::Application for App {
|
|||
);
|
||||
|
||||
if matches!(self.state, State::Locked { .. }) {
|
||||
return get_lock_surface(surface_id, output).chain({
|
||||
return Task::batch([get_lock_surface(surface_id, output).chain({
|
||||
cosmic::task::message(cosmic::Action::Cosmic(
|
||||
cosmic::app::Action::Surface(msg),
|
||||
))
|
||||
});
|
||||
})]);
|
||||
}
|
||||
}
|
||||
OutputEvent::Removed => {
|
||||
|
|
@ -966,15 +945,11 @@ impl cosmic::Application for App {
|
|||
.zip(self.common.output_names.get(output))
|
||||
{
|
||||
let subsurface_id = SurfaceId::unique();
|
||||
self.common
|
||||
.subsurface_outputs
|
||||
.insert(subsurface_id, output.clone());
|
||||
let surface_id = *surface_id;
|
||||
self.common.surface_names.insert(surface_id, name.clone());
|
||||
self.common
|
||||
.surface_names
|
||||
.insert(subsurface_id, name.clone());
|
||||
|
||||
let msg = cosmic::surface::action::subsurface(
|
||||
move |_: &mut App| SctkSubsurfaceSettings {
|
||||
parent: surface_id,
|
||||
|
|
@ -995,7 +970,7 @@ impl cosmic::Application for App {
|
|||
cosmic::app::Action::Surface(msg),
|
||||
)));
|
||||
} else {
|
||||
tracing::error!("no rectangle for subsurface creation...");
|
||||
tracing::error!("no rectangle for subsurface...");
|
||||
}
|
||||
}
|
||||
return Task::batch(commands);
|
||||
|
|
@ -1010,11 +985,11 @@ impl cosmic::Application for App {
|
|||
self.common.window_size.remove(surface_id);
|
||||
commands.push(destroy_lock_surface(*surface_id));
|
||||
}
|
||||
if cfg!(feature = "logind") && self.flags.logind_available {
|
||||
if cfg!(feature = "logind") {
|
||||
return Task::batch(commands);
|
||||
// When logind is available, stick around for more lock signals
|
||||
// When using logind feature, stick around for more lock signals
|
||||
} else {
|
||||
// When logind is not available, exit immediately after unlocking
|
||||
// When not using logind feature, exit immediately after unlocking
|
||||
//TODO: cleaner method to exit?
|
||||
process::exit(0);
|
||||
}
|
||||
|
|
@ -1034,10 +1009,8 @@ impl cosmic::Application for App {
|
|||
Message::DropdownToggle(dropdown) => {
|
||||
if self.dropdown_opt == Some(dropdown) {
|
||||
self.dropdown_opt = None;
|
||||
return self.common.dropdown_blur_rects(false);
|
||||
} else {
|
||||
self.dropdown_opt = Some(dropdown);
|
||||
return self.common.dropdown_blur_rects(true);
|
||||
}
|
||||
}
|
||||
Message::Inhibit(inhibit) => match self.state {
|
||||
|
|
@ -1049,19 +1022,15 @@ impl cosmic::Application for App {
|
|||
}
|
||||
},
|
||||
Message::KeyboardLayout(layout_i) => {
|
||||
if let Some(keyboard_layout) = &self.common.keyboard_layout {
|
||||
keyboard_layout.set_group(layout_i as u32);
|
||||
if layout_i < self.common.active_layouts.len() {
|
||||
self.common.active_layouts.swap(0, layout_i);
|
||||
self.common.set_xkb_config(&self.flags.user_data);
|
||||
}
|
||||
self.common.current_keyboard_layout = layout_i;
|
||||
if self.dropdown_opt == Some(Dropdown::Keyboard) {
|
||||
self.dropdown_opt = None;
|
||||
return self.common.dropdown_blur_rects(false);
|
||||
self.dropdown_opt = None
|
||||
}
|
||||
}
|
||||
Message::Submit(value) => {
|
||||
if value.is_empty() {
|
||||
return Task::none();
|
||||
}
|
||||
self.common.error_opt = None;
|
||||
self.authenticating = true;
|
||||
match self.value_tx_opt.take() {
|
||||
|
|
@ -1220,7 +1189,8 @@ impl cosmic::Application for App {
|
|||
}),
|
||||
);
|
||||
|
||||
if cfg!(feature = "logind") && self.flags.logind_available {
|
||||
#[cfg(feature = "logind")]
|
||||
{
|
||||
subscriptions.push(crate::logind::subscription());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,27 +13,6 @@ use zbus::Connection;
|
|||
use crate::common;
|
||||
use crate::locker::Message;
|
||||
|
||||
/// Checks whether logind (either elogind or systemd-logind) is reachable on the system bus.
|
||||
pub fn is_available() -> bool {
|
||||
fn ping() -> zbus::Result<()> {
|
||||
let connection = zbus::blocking::Connection::system()?;
|
||||
connection.call_method(
|
||||
Some("org.freedesktop.login1"),
|
||||
"/org/freedesktop/login1",
|
||||
Some("org.freedesktop.DBus.Peer"),
|
||||
"Ping",
|
||||
&(),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
if let Err(err) = ping() {
|
||||
tracing::info!("logind not available: {}", err);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn power_off() -> zbus::Result<()> {
|
||||
let connection = Connection::system().await?;
|
||||
let manager = ManagerProxy::new(&connection).await?;
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
}
|
||||
}
|
||||
|
||||
// Enable jpeg-xl support for image-rs.
|
||||
let _ = jxl_oxide::integration::register_image_decoding_hook();
|
||||
|
||||
match pwd::Passwd::current_user() {
|
||||
Some(current_user) => match current_user.name.as_str() {
|
||||
"cosmic-greeter" => greeter::main(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue