Skip to content

Commit

Permalink
Merge pull request #291 from mahkoh/jorth/session-restore
Browse files Browse the repository at this point in the history
portal: implement session restoration
  • Loading branch information
mahkoh authored Oct 11, 2024
2 parents 6e5d8f5 + 2b55278 commit 06d7fff
Show file tree
Hide file tree
Showing 39 changed files with 984 additions and 377 deletions.
6 changes: 4 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ ash = "0.38.0"
gpu-alloc = "0.6.0"
gpu-alloc-ash = "0.7.0"
serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.128"
enum-map = "2.7.3"
png = "0.17.13"
rustc-demangle = { version = "0.1.24", optional = true }
Expand Down
2 changes: 2 additions & 0 deletions release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
- Allow X windows to scale themselves.
- Implement ext-image-capture-source-v1.
- Implement ext-image-copy-capture-v1.
- Implement screencast session restoration.
- Fix screen sharing in zoom.

# 1.6.0 (2024-09-25)

Expand Down
1 change: 1 addition & 0 deletions src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ fn start_compositor2(
cpu_worker,
ui_drag_enabled: Cell::new(true),
ui_drag_threshold_squared: Cell::new(10),
toplevels: Default::default(),
});
state.tracker.register(ClientId::from_raw(0));
create_dummy_output(&state);
Expand Down
11 changes: 9 additions & 2 deletions src/ei/ei_ifs/ei_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use {
wire_ei::{
ei_device::{
ClientFrame, ClientStartEmulating, ClientStopEmulating, Destroyed, DeviceType,
Done, EiDeviceRequestHandler, Interface, Paused, Region, Release, Resumed,
ServerFrame, ServerStartEmulating,
Done, EiDeviceRequestHandler, Interface, Paused, Region, RegionMappingId, Release,
Resumed, ServerFrame, ServerStartEmulating,
},
EiDeviceId,
},
Expand Down Expand Up @@ -100,6 +100,13 @@ impl EiDevice {
});
}

pub fn send_region_mapping_id(&self, mapping_id: &str) {
self.client.event(RegionMappingId {
self_id: self.id,
mapping_id,
});
}

#[expect(dead_code)]
pub fn send_paused(&self, serial: u32) {
self.client.event(Paused {
Expand Down
1 change: 1 addition & 0 deletions src/ei/ei_ifs/ei_seat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ impl EiSeat {
apply!(EI_CAP_KEYBOARD, create_keyboard);
apply!(EI_CAP_TOUCHSCREEN, create_touchscreen);
for output in self.client.state.root.outputs.lock().values() {
device.send_region_mapping_id(&output.global.connector.name);
device.send_region(
output.node_absolute_position(),
output.global.persistent.scale.get(),
Expand Down
34 changes: 25 additions & 9 deletions src/ifs/jay_compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,18 @@ use {
leaks::Tracker,
object::{Object, Version},
screenshoter::take_screenshot,
utils::errorfmt::ErrorFmt,
utils::{errorfmt::ErrorFmt, toplevel_identifier::ToplevelIdentifier},
wire::{jay_compositor::*, JayCompositorId, JayScreenshotId},
},
bstr::ByteSlice,
log::Level,
std::{cell::Cell, ops::Deref, rc::Rc},
std::{cell::Cell, ops::Deref, rc::Rc, str::FromStr},
thiserror::Error,
};

pub const CREATE_EI_SESSION_SINCE: Version = Version(5);
pub const SCREENSHOT_SPLITUP_SINCE: Version = Version(6);
pub const GET_TOPLEVEL_SINCE: Version = Version(12);

pub struct JayCompositorGlobal {
name: GlobalName,
Expand Down Expand Up @@ -71,7 +72,7 @@ impl Global for JayCompositorGlobal {
}

fn version(&self) -> u32 {
11
12
}

fn required_caps(&self) -> ClientCaps {
Expand Down Expand Up @@ -364,12 +365,7 @@ impl JayCompositorRequestHandler for JayCompositor {

fn select_toplevel(&self, req: SelectToplevel, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let seat = self.client.lookup(req.seat)?;
let obj = Rc::new(JaySelectToplevel {
id: req.id,
client: self.client.clone(),
tracker: Default::default(),
destroyed: Cell::new(false),
});
let obj = JaySelectToplevel::new(&self.client, req.id, self.version);
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
let selector = JayToplevelSelector {
Expand Down Expand Up @@ -422,6 +418,26 @@ impl JayCompositorRequestHandler for JayCompositor {
self.client.add_client_obj(&obj)?;
Ok(())
}

fn get_toplevel(&self, req: GetToplevel<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let obj = JaySelectToplevel::new(&self.client, req.id, self.version);
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
let tl = match ToplevelIdentifier::from_str(req.toplevel_id) {
Ok(id) => self
.client
.state
.toplevels
.get(&id)
.and_then(|w| w.upgrade()),
Err(e) => {
log::error!("Could not parse toplevel id: {}", ErrorFmt(e));
None
}
};
obj.done(tl);
Ok(())
}
}

object_base! {
Expand Down
54 changes: 41 additions & 13 deletions src/ifs/jay_select_toplevel.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use {
crate::{
client::{Client, ClientError},
ifs::{jay_toplevel::JayToplevel, wl_seat::ToplevelSelector},
ifs::{
jay_toplevel::{JayToplevel, ID_SINCE},
wl_seat::ToplevelSelector,
},
leaks::Tracker,
object::{Object, Version},
tree::ToplevelNode,
Expand All @@ -17,6 +20,7 @@ pub struct JaySelectToplevel {
pub client: Rc<Client>,
pub tracker: Tracker<Self>,
pub destroyed: Cell<bool>,
pub version: Version,
}

pub struct JayToplevelSelector {
Expand All @@ -35,38 +39,62 @@ impl Drop for JayToplevelSelector {
if self.jst.destroyed.get() {
return;
}
let id = match self.tl.take() {
None => JayToplevelId::NONE,
self.jst.done(self.tl.take());
}
}

impl JaySelectToplevel {
pub fn done(&self, tl: Option<Rc<dyn ToplevelNode>>) {
let jtl = match tl {
None => None,
Some(toplevel) => {
let id = match self.jst.client.new_id() {
let id = match self.client.new_id() {
Ok(id) => id,
Err(e) => {
self.jst.client.error(e);
self.client.error(e);
return;
}
};
let jtl = Rc::new(JayToplevel {
id,
client: self.jst.client.clone(),
client: self.client.clone(),
tracker: Default::default(),
toplevel,
destroyed: Cell::new(false),
version: self.version,
});
track!(self.jst.client, jtl);
self.jst.client.add_server_obj(&jtl);
track!(self.client, jtl);
self.client.add_server_obj(&jtl);
jtl.toplevel
.tl_data()
.jay_toplevels
.set((jtl.client.id, jtl.id), jtl.clone());
jtl.id
Some(jtl)
}
};
self.jst.send_done(id);
let _ = self.jst.client.remove_obj(&*self.jst);
match jtl {
None => self.send_done(JayToplevelId::NONE),
Some(jtl) => {
self.send_done(jtl.id);
if jtl.version >= ID_SINCE {
jtl.send_id();
jtl.send_done();
}
}
}
let _ = self.client.remove_obj(self);
}

pub fn new(client: &Rc<Client>, id: JaySelectToplevelId, version: Version) -> Rc<Self> {
Rc::new(JaySelectToplevel {
id,
client: client.clone(),
tracker: Default::default(),
destroyed: Cell::new(false),
version,
})
}
}

impl JaySelectToplevel {
fn send_done(&self, id: JayToplevelId) {
self.client.event(Done {
self_id: self.id,
Expand Down
15 changes: 15 additions & 0 deletions src/ifs/jay_toplevel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ use {
thiserror::Error,
};

pub const ID_SINCE: Version = Version(12);

pub struct JayToplevel {
pub id: JayToplevelId,
pub client: Rc<Client>,
pub tracker: Tracker<Self>,
pub toplevel: Rc<dyn ToplevelNode>,
pub destroyed: Cell<bool>,
pub version: Version,
}

impl JayToplevel {
Expand All @@ -35,6 +38,18 @@ impl JayToplevel {
fn send_destroyed(&self) {
self.client.event(Destroyed { self_id: self.id });
}

pub fn send_id(&self) {
let s = self.toplevel.tl_data().identifier.get().to_string();
self.client.event(Id {
self_id: self.id,
id: &s,
})
}

pub fn send_done(&self) {
self.client.event(Done { self_id: self.id })
}
}

impl JayToplevelRequestHandler for JayToplevel {
Expand Down
2 changes: 1 addition & 1 deletion src/ifs/wl_seat/pointer_owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1227,7 +1227,7 @@ impl UiDragUsecase for TileDragUsecase {
return;
};
let detach = || {
let placeholder = Rc::new(PlaceholderNode::new_empty(&seat.state));
let placeholder = Rc::new_cyclic(|weak| PlaceholderNode::new_empty(&seat.state, weak));
src_parent
.clone()
.cnode_replace_child(src.tl_as_node(), placeholder.clone());
Expand Down
34 changes: 16 additions & 18 deletions src/ifs/wl_surface/x_surface/xwindow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,18 +205,21 @@ impl Xwindow {
if xsurface.xwindow.is_some() {
return Err(XWindowError::AlreadyAttached);
}
let tld = ToplevelData::new(
&data.state,
data.info.title.borrow_mut().clone().unwrap_or_default(),
Some(surface.client.clone()),
);
tld.pos.set(surface.extents.get());
let slf = Rc::new(Self {
id: data.state.node_ids.next(),
data: data.clone(),
display_link: Default::default(),
toplevel_data: tld,
x: xsurface,
let slf = Rc::new_cyclic(|weak| {
let tld = ToplevelData::new(
&data.state,
data.info.title.borrow_mut().clone().unwrap_or_default(),
Some(surface.client.clone()),
weak,
);
tld.pos.set(surface.extents.get());
Self {
id: data.state.node_ids.next(),
data: data.clone(),
display_link: Default::default(),
toplevel_data: tld,
x: xsurface,
}
});
slf.x.xwindow.set(Some(slf.clone()));
slf.x.surface.set_toplevel(Some(slf.clone()));
Expand Down Expand Up @@ -344,12 +347,7 @@ impl Node for Xwindow {
}
let rect = self.x.surface.buffer_abs_pos.get();
if x < rect.width() && y < rect.height() {
tree.push(FoundNode {
node: self.x.surface.clone(),
x,
y,
});
return FindTreeResult::AcceptsInput;
return self.x.surface.find_tree_at_(x, y, tree);
}
FindTreeResult::Other
}
Expand Down
2 changes: 1 addition & 1 deletion src/ifs/wl_surface/xdg_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ impl XdgSurfaceRequestHandler for XdgSurface {
);
return Err(XdgSurfaceError::AlreadyConstructed);
}
let toplevel = Rc::new(XdgToplevel::new(req.id, slf));
let toplevel = Rc::new_cyclic(|weak| XdgToplevel::new(req.id, slf, weak));
track!(self.surface.client, toplevel);
self.surface.client.add_client_obj(&toplevel)?;
self.ext.set(Some(toplevel.clone()));
Expand Down
5 changes: 3 additions & 2 deletions src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use {
cell::{Cell, RefCell},
fmt::{Debug, Formatter},
mem,
rc::Rc,
rc::{Rc, Weak},
},
thiserror::Error,
};
Expand Down Expand Up @@ -115,7 +115,7 @@ impl Debug for XdgToplevel {
}

impl XdgToplevel {
pub fn new(id: XdgToplevelId, surface: &Rc<XdgSurface>) -> Self {
pub fn new(id: XdgToplevelId, surface: &Rc<XdgSurface>, slf: &Weak<Self>) -> Self {
let mut states = AHashSet::new();
states.insert(STATE_TILED_LEFT);
states.insert(STATE_TILED_RIGHT);
Expand All @@ -141,6 +141,7 @@ impl XdgToplevel {
state,
String::new(),
Some(surface.surface.client.clone()),
slf,
),
drag: Default::default(),
is_mapped: Cell::new(false),
Expand Down
Loading

0 comments on commit 06d7fff

Please sign in to comment.