OSK integration
This commit is contained in:
parent
db39ee661d
commit
ce726d8470
6 changed files with 120 additions and 28 deletions
|
|
@ -10,6 +10,7 @@ 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_config::CosmicConfigEntry;
|
||||
use cosmic_greeter_daemon::{BgSource, UserData};
|
||||
use cosmic_protocols::keyboard_layout::v1::client::zcosmic_keyboard_layout_v1::ZcosmicKeyboardLayoutV1;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
|
@ -19,6 +20,7 @@ use wayland_client::{Connection, Proxy};
|
|||
|
||||
use crate::keyboard_layout_wayland;
|
||||
|
||||
pub const MAX_WIDTH: f32 = 866.;
|
||||
pub const DEFAULT_MENU_ITEM_HEIGHT: f32 = 36.;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
|
@ -28,6 +30,18 @@ pub struct ActiveLayout {
|
|||
pub variant: String,
|
||||
}
|
||||
|
||||
impl ActiveLayout {
|
||||
pub fn name(&self) -> String {
|
||||
let mut name = self.layout.clone();
|
||||
if !self.variant.is_empty() {
|
||||
name.push_str(" (");
|
||||
name.push_str(&self.variant);
|
||||
name.push_str(")");
|
||||
}
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Common<M> {
|
||||
pub wayland_connection: Option<Connection>,
|
||||
pub keyboard_layout: Option<ZcosmicKeyboardLayoutV1>,
|
||||
|
|
@ -67,6 +81,7 @@ pub enum Message {
|
|||
Focus(SurfaceId),
|
||||
Key(Modifiers, Key, Option<SmolStr>),
|
||||
NetworkIcon(Option<&'static str>),
|
||||
OnScreenKeyboard,
|
||||
SubsurfaceOpened(SurfaceId),
|
||||
OutputEvent(OutputEvent, WlOutput),
|
||||
PowerInfo(Option<(f64, bool, bool)>),
|
||||
|
|
@ -276,6 +291,26 @@ impl<M: From<Message> + Send + 'static> Common<M> {
|
|||
self.network_icon_opt =
|
||||
network_icon_opt.map(|name| widget::icon::from_name(name).into());
|
||||
}
|
||||
Message::OnScreenKeyboard => {
|
||||
use cosmic_osk_config::Config;
|
||||
match Config::handler() {
|
||||
Ok(handler) => {
|
||||
let mut config = match Config::get_entry(&handler) {
|
||||
Ok(config) => config,
|
||||
Err((errs, config)) => {
|
||||
tracing::warn!("failed to parse OSK config: {:?}", errs);
|
||||
config
|
||||
}
|
||||
};
|
||||
if let Err(err) = config.set_always_shown(&handler, !config.always_shown) {
|
||||
tracing::error!("failed to set OSK always_shown config: {}", err);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("failed to create OSK config handler: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::OutputEvent(output_event, output) => {
|
||||
if self.wayland_connection.is_none() {
|
||||
if let Some(backend) = output.backend().upgrade() {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use cosmic::cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Gravity
|
|||
use cosmic::cosmic_config::{self, ConfigSet};
|
||||
use cosmic::cosmic_theme::{self, CosmicPalette};
|
||||
use cosmic::desktop::fde::{DesktopEntry, get_languages_from_env};
|
||||
use cosmic::iced::core::text::{Ellipsize, EllipsizeHeightLimit};
|
||||
use cosmic::iced::event::listen_with;
|
||||
use cosmic::iced::event::wayland::OutputEvent;
|
||||
use cosmic::iced::futures::SinkExt;
|
||||
|
|
@ -41,7 +42,7 @@ use std::num::NonZeroU32;
|
|||
use std::process::Stdio;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{fs, io, process};
|
||||
use std::{fs, io, process, thread};
|
||||
use tokio::process::Child;
|
||||
use tokio::time;
|
||||
use tracing::metadata::LevelFilter;
|
||||
|
|
@ -52,7 +53,7 @@ use wayland_client::Proxy;
|
|||
use wayland_client::protocol::wl_output::WlOutput;
|
||||
use zbus::{Connection, proxy};
|
||||
|
||||
use crate::common::{self, Common, DEFAULT_MENU_ITEM_HEIGHT};
|
||||
use crate::common::{self, Common, DEFAULT_MENU_ITEM_HEIGHT, MAX_WIDTH};
|
||||
use crate::fl;
|
||||
|
||||
static USERNAME_ID: LazyLock<iced::id::Id> = LazyLock::new(|| iced::id::Id::new("username-id"));
|
||||
|
|
@ -280,6 +281,15 @@ pub fn main() -> Result<(), Box<dyn Error>> {
|
|||
sessions
|
||||
};
|
||||
|
||||
match process::Command::new("cosmic-osk").spawn() {
|
||||
Ok(mut child) => {
|
||||
thread::spawn(move || child.wait().unwrap());
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::warn!("failed to spawn cosmic-osk: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
let flags = Flags {
|
||||
user_icons: user_datas
|
||||
.iter_mut()
|
||||
|
|
@ -482,9 +492,9 @@ impl App {
|
|||
.window_size
|
||||
.get(&id)
|
||||
.map(|s| s.width)
|
||||
.unwrap_or(800.);
|
||||
let menu_width = if window_width > 800. {
|
||||
800.
|
||||
.unwrap_or(MAX_WIDTH);
|
||||
let menu_width = if window_width > MAX_WIDTH {
|
||||
MAX_WIDTH
|
||||
} else {
|
||||
window_width
|
||||
};
|
||||
|
|
@ -584,9 +594,19 @@ impl App {
|
|||
};
|
||||
|
||||
let mut input_button = widget::popover(
|
||||
widget::button::custom(widget::icon::from_name("input-keyboard-symbolic"))
|
||||
widget::container(
|
||||
widget::button::custom(
|
||||
widget::text(
|
||||
self.common.active_layouts[self.common.current_keyboard_layout].name(),
|
||||
)
|
||||
.ellipsize(Ellipsize::End(EllipsizeHeightLimit::Lines(1)))
|
||||
.height(16)
|
||||
.center(),
|
||||
)
|
||||
.padding(12.0)
|
||||
.on_press(Message::DropdownToggle(Dropdown::Keyboard)),
|
||||
)
|
||||
.max_width(92),
|
||||
)
|
||||
.position(widget::popover::Position::Bottom);
|
||||
if matches!(self.dropdown_opt, Some(Dropdown::Keyboard)) {
|
||||
|
|
@ -702,6 +722,13 @@ impl App {
|
|||
text(fl!("accessibility")),
|
||||
widget::tooltip::Position::Top
|
||||
),
|
||||
widget::tooltip(
|
||||
widget::button::custom(widget::icon::from_name("input-keyboard-symbolic"))
|
||||
.padding(12.0)
|
||||
.on_press(Message::Common(common::Message::OnScreenKeyboard)),
|
||||
text(fl!("on-screen-keyboard")),
|
||||
widget::tooltip::Position::Top,
|
||||
),
|
||||
widget::tooltip(
|
||||
input_button,
|
||||
text(fl!("keyboard-layout")),
|
||||
|
|
@ -965,7 +992,7 @@ impl App {
|
|||
appearance
|
||||
},
|
||||
)))
|
||||
.width(Length::Fixed(800.0));
|
||||
.width(Length::Fixed(MAX_WIDTH));
|
||||
let menu = if let Some(t) = self.common.rectangle_tracker.as_ref() {
|
||||
Element::from(t.container((id, false), menu))
|
||||
} else {
|
||||
|
|
@ -1253,10 +1280,10 @@ impl cosmic::Application for App {
|
|||
let unwrapped_size = size
|
||||
.map(|s| (s.0.unwrap_or(1920), s.1.unwrap_or(1080)))
|
||||
.unwrap_or((1920, 1080));
|
||||
let (loc, sub_size) = if unwrapped_size.0 > 800 {
|
||||
let (loc, sub_size) = if unwrapped_size.0 as f32 > MAX_WIDTH {
|
||||
(
|
||||
Point::new(unwrapped_size.0 as f32 / 2. - 400., 32.),
|
||||
Size::new(800., unwrapped_size.1 as f32 - 32.),
|
||||
Point::new((unwrapped_size.0 as f32 - MAX_WIDTH) / 2., 32.),
|
||||
Size::new(MAX_WIDTH, unwrapped_size.1 as f32 - 32.),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
|
|
@ -1872,8 +1899,8 @@ impl cosmic::Application for App {
|
|||
tracing::error!("Failed to find subsurface menu id");
|
||||
return Task::none();
|
||||
};
|
||||
let loc = if size.width > 800. {
|
||||
Point::new(size.width / 2. - 400., 32.)
|
||||
let loc = if size.width > MAX_WIDTH {
|
||||
Point::new((size.width - MAX_WIDTH) / 2., 32.)
|
||||
} else {
|
||||
Point::new(0., 32.)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
use color_eyre::eyre::WrapErr;
|
||||
use cosmic::app::{Core, Settings, Task};
|
||||
use cosmic::cctk::wayland_protocols::xdg::shell::client::xdg_positioner::Gravity;
|
||||
use cosmic::iced::core::text::{Ellipsize, EllipsizeHeightLimit};
|
||||
use cosmic::iced::event::wayland::{OutputEvent, SessionLockEvent};
|
||||
use cosmic::iced::futures::{self, SinkExt};
|
||||
use cosmic::iced::platform_specific::shell::wayland::commands::session_lock::{
|
||||
|
|
@ -34,7 +35,7 @@ use tracing_subscriber::{EnvFilter, fmt};
|
|||
use wayland_client::Proxy;
|
||||
use wayland_client::protocol::wl_output::WlOutput;
|
||||
|
||||
use crate::common::{self, Common, DEFAULT_MENU_ITEM_HEIGHT};
|
||||
use crate::common::{self, Common, DEFAULT_MENU_ITEM_HEIGHT, MAX_WIDTH};
|
||||
use crate::fl;
|
||||
|
||||
fn lockfile_opt() -> Option<PathBuf> {
|
||||
|
|
@ -326,9 +327,9 @@ impl App {
|
|||
.window_size
|
||||
.get(&surface_id)
|
||||
.map(|s| s.width)
|
||||
.unwrap_or(800.);
|
||||
let menu_width = if window_width > 800. {
|
||||
800.
|
||||
.unwrap_or(MAX_WIDTH);
|
||||
let menu_width = if window_width > MAX_WIDTH {
|
||||
MAX_WIDTH
|
||||
} else {
|
||||
window_width
|
||||
};
|
||||
|
|
@ -417,9 +418,19 @@ impl App {
|
|||
};
|
||||
|
||||
let mut input_button = widget::popover(
|
||||
widget::button::custom(widget::icon::from_name("input-keyboard-symbolic"))
|
||||
widget::container(
|
||||
widget::button::custom(
|
||||
widget::text(
|
||||
self.common.active_layouts[self.common.current_keyboard_layout].name(),
|
||||
)
|
||||
.ellipsize(Ellipsize::End(EllipsizeHeightLimit::Lines(1)))
|
||||
.height(16)
|
||||
.center(),
|
||||
)
|
||||
.padding(12.0)
|
||||
.on_press(Message::DropdownToggle(Dropdown::Keyboard)),
|
||||
)
|
||||
.max_width(92),
|
||||
)
|
||||
.position(widget::popover::Position::Bottom);
|
||||
if matches!(self.dropdown_opt, Some(Dropdown::Keyboard)) {
|
||||
|
|
@ -443,6 +454,13 @@ impl App {
|
|||
.padding(12.0)
|
||||
.on_press(Message::None),
|
||||
*/
|
||||
widget::tooltip(
|
||||
widget::button::custom(widget::icon::from_name("input-keyboard-symbolic"))
|
||||
.padding(12.0)
|
||||
.on_press(Message::Common(common::Message::OnScreenKeyboard)),
|
||||
widget::text(fl!("on-screen-keyboard")),
|
||||
widget::tooltip::Position::Top,
|
||||
),
|
||||
widget::tooltip(
|
||||
input_button,
|
||||
widget::text(fl!("keyboard-layout")),
|
||||
|
|
@ -783,10 +801,10 @@ impl cosmic::Application for App {
|
|||
let unwrapped_size = size
|
||||
.map(|s| (s.0.unwrap_or(1920), s.1.unwrap_or(1080)))
|
||||
.unwrap_or((1920, 1080));
|
||||
let (loc, sub_size) = if unwrapped_size.0 > 800 {
|
||||
let (loc, sub_size) = if unwrapped_size.0 as f32 > MAX_WIDTH {
|
||||
(
|
||||
Point::new(unwrapped_size.0 as f32 / 2. - 400., 32.),
|
||||
Size::new(800., unwrapped_size.1 as f32 - 32.),
|
||||
Size::new(MAX_WIDTH, unwrapped_size.1 as f32 - 32.),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
|
|
@ -864,10 +882,10 @@ impl cosmic::Application for App {
|
|||
let unwrapped_size = size
|
||||
.map(|s| (s.0.unwrap_or(1920), s.1.unwrap_or(1080)))
|
||||
.unwrap_or((1920, 1080));
|
||||
let (loc, sub_size) = if unwrapped_size.0 > 800 {
|
||||
let (loc, sub_size) = if unwrapped_size.0 as f32 > MAX_WIDTH {
|
||||
(
|
||||
Point::new(unwrapped_size.0 as f32 / 2. - 400., 32.),
|
||||
Size::new(800., unwrapped_size.1 as f32 - 32.),
|
||||
Size::new(MAX_WIDTH, unwrapped_size.1 as f32 - 32.),
|
||||
)
|
||||
} else {
|
||||
(Point::ORIGIN, Size::new(1920., 1080.))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue