autocommit 2022-04-17 17:08:31 CEST
This commit is contained in:
parent
50b792db78
commit
a30306e3d5
23 changed files with 390 additions and 42 deletions
|
|
@ -27,6 +27,7 @@ use {
|
||||||
},
|
},
|
||||||
std::time::Duration,
|
std::time::Duration,
|
||||||
};
|
};
|
||||||
|
use jay_config::keyboard::syms::{SYM_a, SYM_e, SYM_o};
|
||||||
|
|
||||||
const MOD: Modifiers = ALT;
|
const MOD: Modifiers = ALT;
|
||||||
|
|
||||||
|
|
@ -77,6 +78,10 @@ fn configure_seat(s: Seat) {
|
||||||
s.bind(MOD | sym, move || s.show_workspace(ws));
|
s.bind(MOD | sym, move || s.show_workspace(ws));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.bind(MOD | SYM_a, || Command::new("spotify-remote").arg("a").spawn());
|
||||||
|
s.bind(MOD | SYM_o, || Command::new("spotify-remote").arg("o").spawn());
|
||||||
|
s.bind(MOD | SYM_e, || Command::new("spotify-remote").arg("e").spawn());
|
||||||
|
|
||||||
fn do_grab(s: Seat, grab: bool) {
|
fn do_grab(s: Seat, grab: bool) {
|
||||||
for device in s.input_devices() {
|
for device in s.input_devices() {
|
||||||
if device.has_capability(CAP_KEYBOARD) {
|
if device.has_capability(CAP_KEYBOARD) {
|
||||||
|
|
|
||||||
48
src/cli.rs
48
src/cli.rs
|
|
@ -3,6 +3,7 @@ mod log;
|
||||||
mod quit;
|
mod quit;
|
||||||
mod screenshot;
|
mod screenshot;
|
||||||
mod set_log_level;
|
mod set_log_level;
|
||||||
|
mod idle;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::compositor::start_compositor,
|
crate::compositor::start_compositor,
|
||||||
|
|
@ -41,6 +42,52 @@ pub enum Cmd {
|
||||||
Quit,
|
Quit,
|
||||||
/// Take a screenshot.
|
/// Take a screenshot.
|
||||||
Screenshot(ScreenshotArgs),
|
Screenshot(ScreenshotArgs),
|
||||||
|
/// Inspect/modify the idle (screensaver) settings.
|
||||||
|
Idle(IdleArgs),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Args, Debug)]
|
||||||
|
pub struct IdleArgs {
|
||||||
|
/// The filename of the saved screenshot
|
||||||
|
///
|
||||||
|
/// If no filename is given, the screenshot will be saved under %Y-%m-%d-%H%M%S_jay.qoi
|
||||||
|
/// in the current directory.
|
||||||
|
///
|
||||||
|
/// The filename can contain the usual strftime parameters.
|
||||||
|
#[clap(subcommand)]
|
||||||
|
pub command: Option<IdleCmd>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand, Debug)]
|
||||||
|
pub enum IdleCmd {
|
||||||
|
/// Print the idle status.
|
||||||
|
Status,
|
||||||
|
/// Set the idle interval.
|
||||||
|
Set(IdleSetArgs),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for IdleCmd {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Args, Debug)]
|
||||||
|
pub struct IdleSetArgs {
|
||||||
|
/// The interval of inactivity after which to disable the screens.
|
||||||
|
///
|
||||||
|
/// This can be either a number in minutes and seconds or the keyword `disabled` to
|
||||||
|
/// disable the screensaver.
|
||||||
|
///
|
||||||
|
/// Minutes and seconds can be specified in any of the following formats:
|
||||||
|
///
|
||||||
|
/// * 1m
|
||||||
|
/// * 1m5s
|
||||||
|
/// * 1m 5s
|
||||||
|
/// * 1min 5sec
|
||||||
|
/// * 1 minute 5 seconds
|
||||||
|
#[clap(verbatim_doc_comment, required = true)]
|
||||||
|
pub interval: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
|
|
@ -136,5 +183,6 @@ pub fn main() {
|
||||||
Cmd::Quit => quit::main(cli.global),
|
Cmd::Quit => quit::main(cli.global),
|
||||||
Cmd::SetLogLevel(a) => set_log_level::main(cli.global, a),
|
Cmd::SetLogLevel(a) => set_log_level::main(cli.global, a),
|
||||||
Cmd::Screenshot(a) => screenshot::main(cli.global, a),
|
Cmd::Screenshot(a) => screenshot::main(cli.global, a),
|
||||||
|
Cmd::Idle(a) => idle::main(cli.global, a),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
138
src/cli/idle.rs
Normal file
138
src/cli/idle.rs
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use crate::cli::{GlobalArgs, IdleArgs, IdleCmd, IdleSetArgs};
|
||||||
|
use crate::tools::tool_client::{Handle, ToolClient};
|
||||||
|
use crate::utils::errorfmt::ErrorFmt;
|
||||||
|
use crate::wire::{jay_compositor, jay_idle, JayIdleId};
|
||||||
|
|
||||||
|
pub fn main(global: GlobalArgs, args: IdleArgs) {
|
||||||
|
let tc = ToolClient::new(global.log_level.into());
|
||||||
|
let idle = Idle {
|
||||||
|
tc: tc.clone(),
|
||||||
|
};
|
||||||
|
tc.run(idle.run(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Idle {
|
||||||
|
tc: Rc<ToolClient>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Idle {
|
||||||
|
async fn run(self, args: IdleArgs) {
|
||||||
|
let tc = &self.tc;
|
||||||
|
let comp = tc.jay_compositor().await;
|
||||||
|
let idle = tc.id();
|
||||||
|
tc.send(jay_compositor::GetIdle {
|
||||||
|
self_id: comp,
|
||||||
|
id: idle,
|
||||||
|
});
|
||||||
|
match args.command.unwrap_or_default() {
|
||||||
|
IdleCmd::Status => self.status(idle).await,
|
||||||
|
IdleCmd::Set(args) => self.set(idle, args).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn status(self, idle: JayIdleId) {
|
||||||
|
let tc = &self.tc;
|
||||||
|
tc.send(jay_idle::GetStatus {
|
||||||
|
self_id: idle,
|
||||||
|
});
|
||||||
|
let interval = Rc::new(Cell::new(0u64));
|
||||||
|
jay_idle::Interval::handle(tc, idle, interval.clone(), |iv, msg| {
|
||||||
|
iv.set(msg.interval);
|
||||||
|
});
|
||||||
|
tc.round_trip().await;
|
||||||
|
let minutes = interval.get() / 60;
|
||||||
|
let seconds = interval.get() % 60;
|
||||||
|
if minutes == 0 && seconds == 0 {
|
||||||
|
println!("Interval: disabled");
|
||||||
|
} else {
|
||||||
|
println!("Interval: {} minutes {} seconds", minutes, seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set(self, idle: JayIdleId, args: IdleSetArgs) {
|
||||||
|
let tc = &self.tc;
|
||||||
|
let interval;
|
||||||
|
if args.interval.len() == 1 && args.interval[0] == "disabled" {
|
||||||
|
interval = 0;
|
||||||
|
} else {
|
||||||
|
let comp = parse_components(&args.interval);
|
||||||
|
let mut minutes = None;
|
||||||
|
let mut seconds = None;
|
||||||
|
let mut pending_num = None;
|
||||||
|
for comp in comp {
|
||||||
|
match comp {
|
||||||
|
Component::Number(_) if pending_num.is_some() => fatal!("missing number unit after {}", pending_num.unwrap()),
|
||||||
|
Component::Number(n) => pending_num = Some(n),
|
||||||
|
|
||||||
|
Component::Minutes(n) if pending_num.is_none() => fatal!("`{}` must be preceded by a number", n),
|
||||||
|
Component::Minutes(_) if minutes.is_some() => fatal!("minutes specified multiple times"),
|
||||||
|
Component::Minutes(_) => minutes = pending_num.take(),
|
||||||
|
|
||||||
|
Component::Seconds(n) if pending_num.is_none() => fatal!("`{}` must be preceded by a number", n),
|
||||||
|
Component::Seconds(_) if seconds.is_some() => fatal!("seconds specified multiple times"),
|
||||||
|
Component::Seconds(_) => seconds = pending_num.take(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pending_num.is_some() {
|
||||||
|
fatal!("missing number unit after {}", pending_num.unwrap());
|
||||||
|
}
|
||||||
|
if minutes.is_none() && seconds.is_none() {
|
||||||
|
fatal!("minutes and/or numbers must be specified");
|
||||||
|
}
|
||||||
|
interval = minutes.unwrap_or(0) * 60 + seconds.unwrap_or(0);
|
||||||
|
}
|
||||||
|
tc.send(jay_idle::SetInterval {
|
||||||
|
self_id: idle,
|
||||||
|
interval,
|
||||||
|
});
|
||||||
|
tc.round_trip().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Component {
|
||||||
|
Number(u64),
|
||||||
|
Minutes(String),
|
||||||
|
Seconds(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_components(args: &[String]) -> Vec<Component> {
|
||||||
|
let mut args = VecDeque::from_iter(args.iter().map(|s| s.to_ascii_lowercase()));
|
||||||
|
let mut res = vec![];
|
||||||
|
while let Some(arg) = args.pop_front() {
|
||||||
|
if arg.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut arg = &arg[..];
|
||||||
|
if is_num(arg.as_bytes()[0]) {
|
||||||
|
if let Some(pos) = arg.as_bytes().iter().position(|&a| !is_num(a)) {
|
||||||
|
args.push_front(arg[pos..].to_string());
|
||||||
|
arg = &arg[..pos];
|
||||||
|
}
|
||||||
|
match u64::from_str(arg) {
|
||||||
|
Ok(n) => res.push(Component::Number(n)),
|
||||||
|
Err(e) => fatal!("Could not parse `{}` as a number: {}", arg, ErrorFmt(e)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(pos) = arg.as_bytes().iter().position(|&a| is_num(a)) {
|
||||||
|
args.push_front(arg[pos..].to_string());
|
||||||
|
arg = &arg[..pos];
|
||||||
|
}
|
||||||
|
let comp = match &arg[..] {
|
||||||
|
"minutes" | "minute" | "min" | "m" => Component::Minutes(arg.to_string()),
|
||||||
|
"seconds" | "second" | "sec" | "s" => Component::Seconds(arg.to_string()),
|
||||||
|
_ => fatal!("Could not parse `{}`", arg),
|
||||||
|
};
|
||||||
|
res.push(comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_num(b: u8) -> bool {
|
||||||
|
matches!(b, b'0'..=b'9')
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,6 @@ use {
|
||||||
queue::AsyncQueue,
|
queue::AsyncQueue,
|
||||||
},
|
},
|
||||||
wire::WlRegistryId,
|
wire::WlRegistryId,
|
||||||
xwayland::XWaylandEvent,
|
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
std::{
|
std::{
|
||||||
|
|
@ -100,7 +99,7 @@ impl Clients {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.spawn2(id, global, socket, uid, pid, secure, None)?;
|
self.spawn2(id, global, socket, uid, pid, secure, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +111,7 @@ impl Clients {
|
||||||
uid: c::uid_t,
|
uid: c::uid_t,
|
||||||
pid: c::pid_t,
|
pid: c::pid_t,
|
||||||
secure: bool,
|
secure: bool,
|
||||||
xwayland_queue: Option<Rc<AsyncQueue<XWaylandEvent>>>,
|
is_xwayland: bool,
|
||||||
) -> Result<Rc<Client>, ClientError> {
|
) -> Result<Rc<Client>, ClientError> {
|
||||||
let data = Rc::new(Client {
|
let data = Rc::new(Client {
|
||||||
id,
|
id,
|
||||||
|
|
@ -125,7 +124,7 @@ impl Clients {
|
||||||
shutdown: Default::default(),
|
shutdown: Default::default(),
|
||||||
dispatch_frame_requests: AsyncQueue::new(),
|
dispatch_frame_requests: AsyncQueue::new(),
|
||||||
tracker: Default::default(),
|
tracker: Default::default(),
|
||||||
xwayland_queue,
|
is_xwayland,
|
||||||
secure,
|
secure,
|
||||||
last_serial: Cell::new(0),
|
last_serial: Cell::new(0),
|
||||||
last_enter_serial: Cell::new(0),
|
last_enter_serial: Cell::new(0),
|
||||||
|
|
@ -224,7 +223,7 @@ pub struct Client {
|
||||||
shutdown: AsyncEvent,
|
shutdown: AsyncEvent,
|
||||||
pub dispatch_frame_requests: AsyncQueue<Rc<WlCallback>>,
|
pub dispatch_frame_requests: AsyncQueue<Rc<WlCallback>>,
|
||||||
pub tracker: Tracker<Client>,
|
pub tracker: Tracker<Client>,
|
||||||
pub xwayland_queue: Option<Rc<AsyncQueue<XWaylandEvent>>>,
|
pub is_xwayland: bool,
|
||||||
pub secure: bool,
|
pub secure: bool,
|
||||||
pub last_serial: Cell<u32>,
|
pub last_serial: Cell<u32>,
|
||||||
pub last_enter_serial: Cell<u32>,
|
pub last_enter_serial: Cell<u32>,
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,7 @@ fn start_compositor2(
|
||||||
xwayland: XWaylandState {
|
xwayland: XWaylandState {
|
||||||
enabled: Cell::new(true),
|
enabled: Cell::new(true),
|
||||||
handler: Default::default(),
|
handler: Default::default(),
|
||||||
|
queue: Default::default(),
|
||||||
},
|
},
|
||||||
socket_path: Default::default(),
|
socket_path: Default::default(),
|
||||||
serial: Default::default(),
|
serial: Default::default(),
|
||||||
|
|
|
||||||
|
|
@ -26,3 +26,4 @@ pub mod zxdg_decoration_manager_v1;
|
||||||
pub mod zxdg_output_manager_v1;
|
pub mod zxdg_output_manager_v1;
|
||||||
pub mod zxdg_output_v1;
|
pub mod zxdg_output_v1;
|
||||||
pub mod zxdg_toplevel_decoration_v1;
|
pub mod zxdg_toplevel_decoration_v1;
|
||||||
|
pub mod jay_idle;
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,14 @@ impl WlDataDevice {
|
||||||
self.manager.client.event(Leave { self_id: self.id })
|
self.manager.client.event(Leave { self_id: self.id })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_enter(&self, surface: WlSurfaceId, x: Fixed, y: Fixed, offer: WlDataOfferId, serial: u32) {
|
pub fn send_enter(
|
||||||
|
&self,
|
||||||
|
surface: WlSurfaceId,
|
||||||
|
x: Fixed,
|
||||||
|
y: Fixed,
|
||||||
|
offer: WlDataOfferId,
|
||||||
|
serial: u32,
|
||||||
|
) {
|
||||||
self.manager.client.event(Enter {
|
self.manager.client.event(Enter {
|
||||||
self_id: self.id,
|
self_id: self.id,
|
||||||
serial,
|
serial,
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,11 @@ impl ZwpPrimarySelectionDeviceV1 {
|
||||||
fn set_selection(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSelectionError> {
|
fn set_selection(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSelectionError> {
|
||||||
let req: SetSelection = self.manager.client.parse(self, parser)?;
|
let req: SetSelection = self.manager.client.parse(self, parser)?;
|
||||||
self.seat.client.validate_serial(req.serial)?;
|
self.seat.client.validate_serial(req.serial)?;
|
||||||
if !self.seat.global.may_modify_primary_selection(&self.seat.client, req.serial) {
|
if !self
|
||||||
|
.seat
|
||||||
|
.global
|
||||||
|
.may_modify_primary_selection(&self.seat.client, req.serial)
|
||||||
|
{
|
||||||
log::warn!("Ignoring disallowed set_selection request");
|
log::warn!("Ignoring disallowed set_selection request");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +77,9 @@ impl ZwpPrimarySelectionDeviceV1 {
|
||||||
} else {
|
} else {
|
||||||
Some(self.manager.client.lookup(req.source)?)
|
Some(self.manager.client.lookup(req.source)?)
|
||||||
};
|
};
|
||||||
self.seat.global.set_primary_selection(src, Some(req.serial))?;
|
self.seat
|
||||||
|
.global
|
||||||
|
.set_primary_selection(src, Some(req.serial))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ use {
|
||||||
std::{ops::Deref, rc::Rc},
|
std::{ops::Deref, rc::Rc},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
};
|
};
|
||||||
|
use crate::ifs::jay_idle::JayIdle;
|
||||||
|
|
||||||
pub struct JayCompositorGlobal {
|
pub struct JayCompositorGlobal {
|
||||||
name: GlobalName,
|
name: GlobalName,
|
||||||
|
|
@ -140,6 +141,18 @@ impl JayCompositor {
|
||||||
self.client.remove_obj(ss.deref())?;
|
self.client.remove_obj(ss.deref())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_idle(&self, parser: MsgParser<'_, '_>) -> Result<(), JayCompositorError> {
|
||||||
|
let req: GetIdle = self.client.parse(self, parser)?;
|
||||||
|
let idle = Rc::new(JayIdle {
|
||||||
|
id: req.id,
|
||||||
|
client: self.client.clone(),
|
||||||
|
tracker: Default::default(),
|
||||||
|
});
|
||||||
|
track!(self.client, idle);
|
||||||
|
self.client.add_client_obj(&idle)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object_base2! {
|
object_base2! {
|
||||||
|
|
@ -150,11 +163,12 @@ object_base2! {
|
||||||
QUIT => quit,
|
QUIT => quit,
|
||||||
SET_LOG_LEVEL => set_log_level,
|
SET_LOG_LEVEL => set_log_level,
|
||||||
TAKE_SCREENSHOT => take_screenshot,
|
TAKE_SCREENSHOT => take_screenshot,
|
||||||
|
GET_IDLE => get_idle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Object for JayCompositor {
|
impl Object for JayCompositor {
|
||||||
fn num_requests(&self) -> u32 {
|
fn num_requests(&self) -> u32 {
|
||||||
TAKE_SCREENSHOT + 1
|
GET_IDLE + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
68
src/ifs/jay_idle.rs
Normal file
68
src/ifs/jay_idle.rs
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
use thiserror::Error;
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
client::Client,
|
||||||
|
leaks::Tracker,
|
||||||
|
object::Object,
|
||||||
|
wire::{jay_idle::*},
|
||||||
|
},
|
||||||
|
std::rc::Rc,
|
||||||
|
};
|
||||||
|
use crate::client::ClientError;
|
||||||
|
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||||
|
use crate::wire::JayIdleId;
|
||||||
|
|
||||||
|
pub struct JayIdle {
|
||||||
|
pub id: JayIdleId,
|
||||||
|
pub client: Rc<Client>,
|
||||||
|
pub tracker: Tracker<Self>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JayIdle {
|
||||||
|
fn send_interval(&self) {
|
||||||
|
let to = self.client.state.idle.timeout.get();
|
||||||
|
self.client.event(Interval {
|
||||||
|
self_id: self.id,
|
||||||
|
interval: to.as_secs(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_status(&self, parser: MsgParser<'_, '_>) -> Result<(), JayIdleError> {
|
||||||
|
let _req: GetStatus = self.client.parse(self, parser)?;
|
||||||
|
self.send_interval();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_interval(&self, parser: MsgParser<'_, '_>) -> Result<(), JayIdleError> {
|
||||||
|
let req: SetInterval = self.client.parse(self, parser)?;
|
||||||
|
let interval = Duration::from_secs(req.interval);
|
||||||
|
self.client.state.idle.set_timeout(interval);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object_base2! {
|
||||||
|
JayIdle;
|
||||||
|
|
||||||
|
GET_STATUS => get_status,
|
||||||
|
SET_INTERVAL => set_interval,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Object for JayIdle {
|
||||||
|
fn num_requests(&self) -> u32 {
|
||||||
|
SET_INTERVAL + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simple_add_obj!(JayIdle);
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum JayIdleError {
|
||||||
|
#[error("Parsing failed")]
|
||||||
|
MsgParserError(#[source] Box<MsgParserError>),
|
||||||
|
#[error(transparent)]
|
||||||
|
ClientError(Box<ClientError>),
|
||||||
|
}
|
||||||
|
efrom!(JayIdleError, ClientError);
|
||||||
|
efrom!(JayIdleError, MsgParserError);
|
||||||
|
|
@ -53,8 +53,8 @@ impl WlCompositor {
|
||||||
let surface = Rc::new(WlSurface::new(surface.id, &self.client));
|
let surface = Rc::new(WlSurface::new(surface.id, &self.client));
|
||||||
track!(self.client, surface);
|
track!(self.client, surface);
|
||||||
self.client.add_client_obj(&surface)?;
|
self.client.add_client_obj(&surface)?;
|
||||||
if let Some(queue) = &self.client.xwayland_queue {
|
if self.client.is_xwayland {
|
||||||
queue.push(XWaylandEvent::SurfaceCreated(surface.clone()));
|
self.client.state.xwayland.queue.push(XWaylandEvent::SurfaceCreated(surface.clone()));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,8 @@ impl WlSeatGlobal {
|
||||||
icon: Option<Rc<WlSurface>>,
|
icon: Option<Rc<WlSurface>>,
|
||||||
serial: u32,
|
serial: u32,
|
||||||
) -> Result<(), WlSeatError> {
|
) -> Result<(), WlSeatError> {
|
||||||
self.pointer_owner.start_drag(self, origin, source, icon, serial)
|
self.pointer_owner
|
||||||
|
.start_drag(self, origin, source, icon, serial)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cancel_dnd(self: &Rc<Self>) {
|
pub fn cancel_dnd(self: &Rc<Self>) {
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ use {
|
||||||
pub struct NodeSeatState {
|
pub struct NodeSeatState {
|
||||||
pointer_foci: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
pointer_foci: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
||||||
kb_foci: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
kb_foci: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
||||||
grabs: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
pointer_grabs: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
||||||
dnd_targets: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
dnd_targets: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,11 +59,11 @@ impl NodeSeatState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn add_pointer_grab(&self, seat: &Rc<WlSeatGlobal>) {
|
pub(super) fn add_pointer_grab(&self, seat: &Rc<WlSeatGlobal>) {
|
||||||
self.grabs.insert(seat.id, seat.clone());
|
self.pointer_grabs.insert(seat.id, seat.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn remove_pointer_grab(&self, seat: &WlSeatGlobal) {
|
pub(super) fn remove_pointer_grab(&self, seat: &WlSeatGlobal) {
|
||||||
self.grabs.remove(&seat.id);
|
self.pointer_grabs.remove(&seat.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn add_dnd_target(&self, seat: &Rc<WlSeatGlobal>) {
|
pub(super) fn add_dnd_target(&self, seat: &Rc<WlSeatGlobal>) {
|
||||||
|
|
@ -89,10 +89,10 @@ impl NodeSeatState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release_kb_focus2(&self, focus_last: bool) {
|
fn release_kb_focus2(&self, focus_last: bool) {
|
||||||
|
self.release_kb_grab();
|
||||||
while let Some((_, seat)) = self.kb_foci.pop() {
|
while let Some((_, seat)) = self.kb_foci.pop() {
|
||||||
seat.ungrab_kb();
|
|
||||||
seat.keyboard_node.set(seat.state.root.clone());
|
seat.keyboard_node.set(seat.state.root.clone());
|
||||||
log::info!("keyboard_node = root");
|
// log::info!("keyboard_node = root");
|
||||||
if focus_last {
|
if focus_last {
|
||||||
if let Some(tl) = seat.toplevel_focus_history.last() {
|
if let Some(tl) = seat.toplevel_focus_history.last() {
|
||||||
seat.focus_node(tl.focus_surface(seat.id));
|
seat.focus_node(tl.focus_surface(seat.id));
|
||||||
|
|
@ -116,7 +116,7 @@ impl NodeSeatState {
|
||||||
fn destroy_node2(&self, node: &dyn Node, focus_last: bool) {
|
fn destroy_node2(&self, node: &dyn Node, focus_last: bool) {
|
||||||
// NOTE: Also called by set_visible(false)
|
// NOTE: Also called by set_visible(false)
|
||||||
|
|
||||||
while let Some((_, seat)) = self.grabs.pop() {
|
while let Some((_, seat)) = self.pointer_grabs.pop() {
|
||||||
seat.pointer_owner.revert_to_default(&seat);
|
seat.pointer_owner.revert_to_default(&seat);
|
||||||
}
|
}
|
||||||
let node_id = node.node_id();
|
let node_id = node.node_id();
|
||||||
|
|
@ -631,7 +631,14 @@ impl WlSeatGlobal {
|
||||||
surface.client.flush();
|
surface.client.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dnd_surface_enter(&self, surface: &WlSurface, dnd: &Dnd, x: Fixed, y: Fixed, serial: u32) {
|
pub fn dnd_surface_enter(
|
||||||
|
&self,
|
||||||
|
surface: &WlSurface,
|
||||||
|
dnd: &Dnd,
|
||||||
|
x: Fixed,
|
||||||
|
y: Fixed,
|
||||||
|
serial: u32,
|
||||||
|
) {
|
||||||
if let Some(src) = &dnd.src {
|
if let Some(src) = &dnd.src {
|
||||||
ipc::offer_source_to::<WlDataDevice>(src, &surface.client);
|
ipc::offer_source_to::<WlDataDevice>(src, &surface.client);
|
||||||
src.for_each_data_offer(|offer| {
|
src.for_each_data_offer(|offer| {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use {
|
||||||
crate::{ifs::wl_seat::WlSeatGlobal, tree::Node, utils::clonecell::CloneCell},
|
crate::{ifs::wl_seat::WlSeatGlobal, tree::Node, utils::clonecell::CloneCell},
|
||||||
std::rc::Rc,
|
std::rc::Rc,
|
||||||
};
|
};
|
||||||
|
use crate::xwayland::XWaylandEvent;
|
||||||
|
|
||||||
pub struct KbOwnerHolder {
|
pub struct KbOwnerHolder {
|
||||||
default: Rc<DefaultKbOwner>,
|
default: Rc<DefaultKbOwner>,
|
||||||
|
|
@ -58,6 +59,9 @@ impl KbOwner for DefaultKbOwner {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log::info!("unfocus {}", old.node_id());
|
log::info!("unfocus {}", old.node_id());
|
||||||
|
if old.node_is_xwayland_surface() && !node.node_is_xwayland_surface() {
|
||||||
|
seat.state.xwayland.queue.push(XWaylandEvent::ActivateRoot);
|
||||||
|
}
|
||||||
old.node_unfocus(seat);
|
old.node_unfocus(seat);
|
||||||
if old.node_seat_state().unfocus(seat) {
|
if old.node_seat_state().unfocus(seat) {
|
||||||
old.node_active_changed(false);
|
old.node_active_changed(false);
|
||||||
|
|
|
||||||
|
|
@ -426,7 +426,12 @@ impl PointerOwner for DndPointerOwner {
|
||||||
target.node_dnd_leave(&self.dnd);
|
target.node_dnd_leave(&self.dnd);
|
||||||
target.node_seat_state().remove_dnd_target(seat);
|
target.node_seat_state().remove_dnd_target(seat);
|
||||||
target = node;
|
target = node;
|
||||||
target.node_dnd_enter(&self.dnd, x, y, seat.state.next_serial(target.node_client().as_deref()));
|
target.node_dnd_enter(
|
||||||
|
&self.dnd,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
seat.state.next_serial(target.node_client().as_deref()),
|
||||||
|
);
|
||||||
target.node_seat_state().add_dnd_target(seat);
|
target.node_seat_state().add_dnd_target(seat);
|
||||||
self.target.set(target);
|
self.target.set(target);
|
||||||
} else if (self.pos_x.get(), self.pos_y.get()) != (x, y) {
|
} else if (self.pos_x.get(), self.pos_y.get()) != (x, y) {
|
||||||
|
|
|
||||||
|
|
@ -866,6 +866,10 @@ impl SizedNode for WlSurface {
|
||||||
fn dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) {
|
fn dnd_motion(&self, dnd: &Dnd, x: Fixed, y: Fixed) {
|
||||||
dnd.seat.dnd_surface_motion(self, dnd, x, y);
|
dnd.seat.dnd_surface_motion(self, dnd, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_xwayland_surface(&self) -> bool {
|
||||||
|
self.client.is_xwayland
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ use {
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode,
|
clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode,
|
||||||
queue::AsyncQueue, smallmap::SmallMap,
|
smallmap::SmallMap,
|
||||||
},
|
},
|
||||||
wire::WlSurfaceId,
|
wire::WlSurfaceId,
|
||||||
wire_xcon::CreateNotify,
|
wire_xcon::CreateNotify,
|
||||||
|
|
@ -139,7 +139,6 @@ pub struct Xwindow {
|
||||||
pub surface: Rc<WlSurface>,
|
pub surface: Rc<WlSurface>,
|
||||||
pub parent_node: CloneCell<Option<Rc<dyn Node>>>,
|
pub parent_node: CloneCell<Option<Rc<dyn Node>>>,
|
||||||
pub focus_history: SmallMap<SeatId, LinkedNode<Rc<dyn ToplevelNode>>, 1>,
|
pub focus_history: SmallMap<SeatId, LinkedNode<Rc<dyn ToplevelNode>>, 1>,
|
||||||
pub events: Rc<AsyncQueue<XWaylandEvent>>,
|
|
||||||
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
||||||
pub display_link: RefCell<Option<LinkedNode<Rc<dyn Node>>>>,
|
pub display_link: RefCell<Option<LinkedNode<Rc<dyn Node>>>>,
|
||||||
pub toplevel_data: ToplevelData,
|
pub toplevel_data: ToplevelData,
|
||||||
|
|
@ -207,7 +206,6 @@ impl Xwindow {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
data: &Rc<XwindowData>,
|
data: &Rc<XwindowData>,
|
||||||
surface: &Rc<WlSurface>,
|
surface: &Rc<WlSurface>,
|
||||||
events: &Rc<AsyncQueue<XWaylandEvent>>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: data.state.node_ids.next(),
|
id: data.state.node_ids.next(),
|
||||||
|
|
@ -216,7 +214,6 @@ impl Xwindow {
|
||||||
surface: surface.clone(),
|
surface: surface.clone(),
|
||||||
parent_node: Default::default(),
|
parent_node: Default::default(),
|
||||||
focus_history: Default::default(),
|
focus_history: Default::default(),
|
||||||
events: events.clone(),
|
|
||||||
workspace: Default::default(),
|
workspace: Default::default(),
|
||||||
display_link: Default::default(),
|
display_link: Default::default(),
|
||||||
toplevel_data: Default::default(),
|
toplevel_data: Default::default(),
|
||||||
|
|
@ -249,7 +246,11 @@ impl Xwindow {
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let extents = self.surface.extents.get();
|
let extents = self.surface.extents.get();
|
||||||
// parent.child_active_changed(self, self.active_surfaces.get() > 0);
|
parent.clone().node_child_active_changed(
|
||||||
|
self,
|
||||||
|
self.toplevel_data.active_surfaces.get() > 0,
|
||||||
|
1,
|
||||||
|
);
|
||||||
parent.node_child_size_changed(self, extents.width(), extents.height());
|
parent.node_child_size_changed(self, extents.width(), extents.height());
|
||||||
parent.node_child_title_changed(
|
parent.node_child_title_changed(
|
||||||
self,
|
self,
|
||||||
|
|
@ -322,8 +323,7 @@ impl SurfaceExt for Xwindow {
|
||||||
self.surface.unset_ext();
|
self.surface.unset_ext();
|
||||||
self.data.window.set(None);
|
self.data.window.set(None);
|
||||||
self.data.surface_id.set(None);
|
self.data.surface_id.set(None);
|
||||||
self.events
|
self.data.state.xwayland.queue.push(XWaylandEvent::SurfaceDestroyed(self.surface.id));
|
||||||
.push(XWaylandEvent::SurfaceDestroyed(self.surface.id));
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -389,7 +389,7 @@ impl SizedNode for Xwindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(&self) {
|
fn close(&self) {
|
||||||
self.events.push(XWaylandEvent::Close(self.data.clone()));
|
self.data.state.xwayland.queue.push(XWaylandEvent::Close(self.data.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn absolute_position(&self) -> Rect {
|
fn absolute_position(&self) -> Rect {
|
||||||
|
|
@ -427,7 +427,7 @@ impl SizedNode for Xwindow {
|
||||||
let old = self.data.info.extents.replace(*rect);
|
let old = self.data.info.extents.replace(*rect);
|
||||||
if old != *rect {
|
if old != *rect {
|
||||||
if !self.data.info.override_redirect.get() {
|
if !self.data.info.override_redirect.get() {
|
||||||
self.events.push(XWaylandEvent::Configure(self.clone()));
|
self.data.state.xwayland.queue.push(XWaylandEvent::Configure(self.clone()));
|
||||||
}
|
}
|
||||||
if old.position() != rect.position() {
|
if old.position() != rect.position() {
|
||||||
self.surface.set_absolute_position(rect.x1(), rect.y1());
|
self.surface.set_absolute_position(rect.x1(), rect.y1());
|
||||||
|
|
@ -482,7 +482,7 @@ impl ToplevelNode for Xwindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate(&self) {
|
fn activate(&self) {
|
||||||
self.events.push(XWaylandEvent::Activate(self.data.clone()));
|
self.data.state.xwayland.queue.push(XWaylandEvent::Activate(self.data.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_floating(self: Rc<Self>) {
|
fn toggle_floating(self: Rc<Self>) {
|
||||||
|
|
@ -503,7 +503,7 @@ impl ToplevelNode for Xwindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(&self) {
|
fn close(&self) {
|
||||||
self.events.push(XWaylandEvent::Close(self.data.clone()));
|
self.data.state.xwayland.queue.push(XWaylandEvent::Close(self.data.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
src/state.rs
10
src/state.rs
|
|
@ -44,6 +44,7 @@ use {
|
||||||
time::Duration,
|
time::Duration,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use crate::xwayland::XWaylandEvent;
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub xkb_ctx: XkbContext,
|
pub xkb_ctx: XkbContext,
|
||||||
|
|
@ -92,6 +93,7 @@ pub struct State {
|
||||||
pub struct XWaylandState {
|
pub struct XWaylandState {
|
||||||
pub enabled: Cell<bool>,
|
pub enabled: Cell<bool>,
|
||||||
pub handler: RefCell<Option<SpawnedFuture<()>>>,
|
pub handler: RefCell<Option<SpawnedFuture<()>>>,
|
||||||
|
pub queue: Rc<AsyncQueue<XWaylandEvent>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IdleState {
|
pub struct IdleState {
|
||||||
|
|
@ -101,6 +103,14 @@ pub struct IdleState {
|
||||||
pub timeout_changed: Cell<bool>,
|
pub timeout_changed: Cell<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IdleState {
|
||||||
|
pub fn set_timeout(&self, timeout: Duration) {
|
||||||
|
self.timeout.set(timeout);
|
||||||
|
self.timeout_changed.set(true);
|
||||||
|
self.change.trigger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct InputDeviceData {
|
pub struct InputDeviceData {
|
||||||
pub handler: SpawnedFuture<()>,
|
pub handler: SpawnedFuture<()>,
|
||||||
pub id: InputDeviceId,
|
pub id: InputDeviceId,
|
||||||
|
|
|
||||||
|
|
@ -359,6 +359,10 @@ pub trait SizedNode: Sized + 'static {
|
||||||
let _ = x;
|
let _ = x;
|
||||||
let _ = y;
|
let _ = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_xwayland_surface(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Node {
|
pub trait Node {
|
||||||
|
|
@ -436,6 +440,7 @@ pub trait Node {
|
||||||
fn node_set_parent(self: Rc<Self>, parent: Rc<dyn Node>);
|
fn node_set_parent(self: Rc<Self>, parent: Rc<dyn Node>);
|
||||||
fn node_client(&self) -> Option<Rc<Client>>;
|
fn node_client(&self) -> Option<Rc<Client>>;
|
||||||
fn node_client_id(&self) -> Option<ClientId>;
|
fn node_client_id(&self) -> Option<ClientId>;
|
||||||
|
fn node_is_xwayland_surface(&self) -> bool;
|
||||||
fn node_into_surface(self: Rc<Self>) -> Option<Rc<WlSurface>>;
|
fn node_into_surface(self: Rc<Self>) -> Option<Rc<WlSurface>>;
|
||||||
fn node_dnd_drop(&self, dnd: &Dnd);
|
fn node_dnd_drop(&self, dnd: &Dnd);
|
||||||
fn node_dnd_leave(&self, dnd: &Dnd);
|
fn node_dnd_leave(&self, dnd: &Dnd);
|
||||||
|
|
@ -644,6 +649,10 @@ impl<T: SizedNode> Node for T {
|
||||||
fn node_client_id(&self) -> Option<ClientId> {
|
fn node_client_id(&self) -> Option<ClientId> {
|
||||||
<Self as SizedNode>::client_id(self)
|
<Self as SizedNode>::client_id(self)
|
||||||
}
|
}
|
||||||
|
fn node_is_xwayland_surface(&self) -> bool {
|
||||||
|
<Self as SizedNode>::is_xwayland_surface(self)
|
||||||
|
}
|
||||||
|
|
||||||
fn node_into_surface(self: Rc<Self>) -> Option<Rc<WlSurface>> {
|
fn node_into_surface(self: Rc<Self>) -> Option<Rc<WlSurface>> {
|
||||||
<Self as SizedNode>::into_surface(&self)
|
<Self as SizedNode>::into_surface(&self)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use {
|
||||||
},
|
},
|
||||||
state::State,
|
state::State,
|
||||||
user_session::import_environment,
|
user_session::import_environment,
|
||||||
utils::{errorfmt::ErrorFmt, oserror::OsError, queue::AsyncQueue, tri::Try},
|
utils::{errorfmt::ErrorFmt, oserror::OsError, tri::Try},
|
||||||
wire::WlSurfaceId,
|
wire::WlSurfaceId,
|
||||||
xcon::XconError,
|
xcon::XconError,
|
||||||
xwayland::{xsocket::allocate_socket, xwm::Wm},
|
xwayland::{xsocket::allocate_socket, xwm::Wm},
|
||||||
|
|
@ -168,7 +168,6 @@ async fn run(
|
||||||
Err(e) => return Err(XWaylandError::ExecFailed(e)),
|
Err(e) => return Err(XWaylandError::ExecFailed(e)),
|
||||||
};
|
};
|
||||||
let client_id = state.clients.id();
|
let client_id = state.clients.id();
|
||||||
let queue = Rc::new(AsyncQueue::new());
|
|
||||||
let client = state.clients.spawn2(
|
let client = state.clients.spawn2(
|
||||||
client_id,
|
client_id,
|
||||||
state,
|
state,
|
||||||
|
|
@ -176,21 +175,22 @@ async fn run(
|
||||||
9999,
|
9999,
|
||||||
9999,
|
9999,
|
||||||
true,
|
true,
|
||||||
Some(queue.clone()),
|
true,
|
||||||
);
|
);
|
||||||
let client = match client {
|
let client = match client {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => return Err(XWaylandError::SpawnClient(e)),
|
Err(e) => return Err(XWaylandError::SpawnClient(e)),
|
||||||
};
|
};
|
||||||
state.eng.fd(&Rc::new(dfdread))?.readable().await?;
|
state.eng.fd(&Rc::new(dfdread))?.readable().await?;
|
||||||
let wm = match Wm::get(state, client, wm1, queue.clone()).await {
|
state.xwayland.queue.clear();
|
||||||
|
let wm = match Wm::get(state, client, wm1).await {
|
||||||
Ok(w) => w,
|
Ok(w) => w,
|
||||||
Err(e) => return Err(XWaylandError::CreateWm(Box::new(e))),
|
Err(e) => return Err(XWaylandError::CreateWm(Box::new(e))),
|
||||||
};
|
};
|
||||||
let wm = state.eng.spawn(wm.run());
|
let wm = state.eng.spawn(wm.run());
|
||||||
state.eng.fd(&Rc::new(pidfd))?.readable().await?;
|
state.eng.fd(&Rc::new(pidfd))?.readable().await?;
|
||||||
drop(wm);
|
drop(wm);
|
||||||
queue.clear();
|
state.xwayland.queue.clear();
|
||||||
stderr_read.await;
|
stderr_read.await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -278,5 +278,6 @@ pub enum XWaylandEvent {
|
||||||
SurfaceDestroyed(WlSurfaceId),
|
SurfaceDestroyed(WlSurfaceId),
|
||||||
Configure(Rc<Xwindow>),
|
Configure(Rc<Xwindow>),
|
||||||
Activate(Rc<XwindowData>),
|
Activate(Rc<XwindowData>),
|
||||||
|
ActivateRoot,
|
||||||
Close(Rc<XwindowData>),
|
Close(Rc<XwindowData>),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use {
|
||||||
state::State,
|
state::State,
|
||||||
tree::{Node, SizedNode},
|
tree::{Node, SizedNode},
|
||||||
utils::{
|
utils::{
|
||||||
bitflags::BitflagsExt, errorfmt::ErrorFmt, linkedlist::LinkedList, queue::AsyncQueue,
|
bitflags::BitflagsExt, errorfmt::ErrorFmt, linkedlist::LinkedList,
|
||||||
},
|
},
|
||||||
wire::WlSurfaceId,
|
wire::WlSurfaceId,
|
||||||
wire_xcon::{
|
wire_xcon::{
|
||||||
|
|
@ -136,7 +136,6 @@ pub struct Wm {
|
||||||
client: Rc<Client>,
|
client: Rc<Client>,
|
||||||
windows: AHashMap<u32, Rc<XwindowData>>,
|
windows: AHashMap<u32, Rc<XwindowData>>,
|
||||||
windows_by_surface_id: AHashMap<WlSurfaceId, Rc<XwindowData>>,
|
windows_by_surface_id: AHashMap<WlSurfaceId, Rc<XwindowData>>,
|
||||||
queue: Rc<AsyncQueue<XWaylandEvent>>,
|
|
||||||
focus_window: Option<Rc<XwindowData>>,
|
focus_window: Option<Rc<XwindowData>>,
|
||||||
last_input_serial: u64,
|
last_input_serial: u64,
|
||||||
|
|
||||||
|
|
@ -162,7 +161,6 @@ impl Wm {
|
||||||
state: &Rc<State>,
|
state: &Rc<State>,
|
||||||
client: Rc<Client>,
|
client: Rc<Client>,
|
||||||
socket: OwnedFd,
|
socket: OwnedFd,
|
||||||
queue: Rc<AsyncQueue<XWaylandEvent>>,
|
|
||||||
) -> Result<Self, XWaylandError> {
|
) -> Result<Self, XWaylandError> {
|
||||||
let c = match Xcon::connect_to_fd(&state.eng, &Rc::new(socket), &[], &[]).await {
|
let c = match Xcon::connect_to_fd(&state.eng, &Rc::new(socket), &[], &[]).await {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
|
|
@ -344,7 +342,6 @@ impl Wm {
|
||||||
client,
|
client,
|
||||||
windows: Default::default(),
|
windows: Default::default(),
|
||||||
windows_by_surface_id: Default::default(),
|
windows_by_surface_id: Default::default(),
|
||||||
queue,
|
|
||||||
focus_window: Default::default(),
|
focus_window: Default::default(),
|
||||||
last_input_serial: 0,
|
last_input_serial: 0,
|
||||||
stack_list: Default::default(),
|
stack_list: Default::default(),
|
||||||
|
|
@ -357,7 +354,7 @@ impl Wm {
|
||||||
pub async fn run(mut self) {
|
pub async fn run(mut self) {
|
||||||
loop {
|
loop {
|
||||||
select! {
|
select! {
|
||||||
e = self.queue.pop().fuse() => self.handle_xwayland_event(e).await,
|
e = self.state.xwayland.queue.pop().fuse() => self.handle_xwayland_event(e).await,
|
||||||
e = self.c.event().fuse() => self.handle_event(&e).await,
|
e = self.c.event().fuse() => self.handle_event(&e).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -371,6 +368,7 @@ impl Wm {
|
||||||
XWaylandEvent::Configure(event) => self.handle_xwayland_configure(event).await,
|
XWaylandEvent::Configure(event) => self.handle_xwayland_configure(event).await,
|
||||||
XWaylandEvent::SurfaceDestroyed(event) => self.handle_xwayland_surface_destroyed(event),
|
XWaylandEvent::SurfaceDestroyed(event) => self.handle_xwayland_surface_destroyed(event),
|
||||||
XWaylandEvent::Activate(window) => self.activate_window(Some(&window)).await,
|
XWaylandEvent::Activate(window) => self.activate_window(Some(&window)).await,
|
||||||
|
XWaylandEvent::ActivateRoot => self.activate_window(None).await,
|
||||||
XWaylandEvent::Close(window) => self.close_window(&window).await,
|
XWaylandEvent::Close(window) => self.close_window(&window).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -896,7 +894,7 @@ impl Wm {
|
||||||
log::error!("The xwindow has already been constructed");
|
log::error!("The xwindow has already been constructed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let window = Rc::new(Xwindow::new(data, &surface, &self.queue));
|
let window = Rc::new(Xwindow::new(data, &surface));
|
||||||
if let Err(e) = window.install() {
|
if let Err(e) = window.install() {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Could not attach the xwindow to the surface: {}",
|
"Could not attach the xwindow to the surface: {}",
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,7 @@ msg set_log_level = 3 {
|
||||||
msg take_screenshot = 4 {
|
msg take_screenshot = 4 {
|
||||||
id: id(jay_screenshot),
|
id: id(jay_screenshot),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msg get_idle = 5 {
|
||||||
|
id: id(jay_idle),
|
||||||
|
}
|
||||||
|
|
|
||||||
18
wire/jay_idle.txt
Normal file
18
wire/jay_idle.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# requests
|
||||||
|
|
||||||
|
msg get_status = 0 {
|
||||||
|
}
|
||||||
|
|
||||||
|
msg set_interval = 1 {
|
||||||
|
interval: pod(u64),
|
||||||
|
}
|
||||||
|
|
||||||
|
# events
|
||||||
|
|
||||||
|
msg interval = 0 {
|
||||||
|
interval: pod(u64),
|
||||||
|
}
|
||||||
|
|
||||||
|
msg inhibitor = 1 {
|
||||||
|
name: str,
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue