Merge pull request #245 from mahkoh/jorth/toplevel-cast
Fix toplevel screencasts with hardware cursors
This commit is contained in:
commit
2579834a60
11 changed files with 191 additions and 37 deletions
|
|
@ -494,6 +494,7 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
screencopies: Default::default(),
|
screencopies: Default::default(),
|
||||||
title_visible: Cell::new(false),
|
title_visible: Cell::new(false),
|
||||||
schedule,
|
schedule,
|
||||||
|
latch_event: Default::default(),
|
||||||
});
|
});
|
||||||
let dummy_workspace = Rc::new(WorkspaceNode {
|
let dummy_workspace = Rc::new(WorkspaceNode {
|
||||||
id: state.node_ids.next(),
|
id: state.node_ids.next(),
|
||||||
|
|
|
||||||
|
|
@ -325,7 +325,7 @@ impl JayCompositorRequestHandler for JayCompositor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_screencast(&self, req: CreateScreencast, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
fn create_screencast(&self, req: CreateScreencast, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
let sc = Rc::new(JayScreencast::new(req.id, &self.client));
|
let sc = Rc::new_cyclic(|slf| JayScreencast::new(req.id, &self.client, slf));
|
||||||
track!(self.client, sc);
|
track!(self.client, sc);
|
||||||
self.client.add_client_obj(&sc)?;
|
self.client.add_client_obj(&sc)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,11 @@ use {
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
scale::Scale,
|
scale::Scale,
|
||||||
state::State,
|
state::State,
|
||||||
tree::{OutputNode, ToplevelNode, WorkspaceNode, WorkspaceNodeId},
|
tree::{LatchListener, OutputNode, ToplevelNode, WorkspaceNode, WorkspaceNodeId},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::{CloneCell, UnsafeCellCloneSafe},
|
clonecell::{CloneCell, UnsafeCellCloneSafe},
|
||||||
errorfmt::ErrorFmt,
|
errorfmt::ErrorFmt,
|
||||||
|
event_listener::EventListener,
|
||||||
numcell::NumCell,
|
numcell::NumCell,
|
||||||
option_ext::OptionExt,
|
option_ext::OptionExt,
|
||||||
},
|
},
|
||||||
|
|
@ -29,7 +30,7 @@ use {
|
||||||
std::{
|
std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
ops::DerefMut,
|
ops::DerefMut,
|
||||||
rc::Rc,
|
rc::{Rc, Weak},
|
||||||
},
|
},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
};
|
};
|
||||||
|
|
@ -75,6 +76,7 @@ pub struct JayScreencast {
|
||||||
pending: Pending,
|
pending: Pending,
|
||||||
need_realloc: Cell<bool>,
|
need_realloc: Cell<bool>,
|
||||||
realloc_scheduled: Cell<bool>,
|
realloc_scheduled: Cell<bool>,
|
||||||
|
latch_listener: EventListener<dyn LatchListener>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -83,6 +85,12 @@ enum Target {
|
||||||
Toplevel(Rc<dyn ToplevelNode>),
|
Toplevel(Rc<dyn ToplevelNode>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LatchListener for JayScreencast {
|
||||||
|
fn after_latch(self: Rc<Self>) {
|
||||||
|
self.schedule_toplevel_screencast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl UnsafeCellCloneSafe for Target {}
|
unsafe impl UnsafeCellCloneSafe for Target {}
|
||||||
|
|
||||||
enum PendingTarget {
|
enum PendingTarget {
|
||||||
|
|
@ -119,7 +127,7 @@ impl JayScreencast {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(id: JayScreencastId, client: &Rc<Client>) -> Self {
|
pub fn new(id: JayScreencastId, client: &Rc<Client>, slf: &Weak<Self>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
|
|
@ -139,10 +147,11 @@ impl JayScreencast {
|
||||||
pending: Default::default(),
|
pending: Default::default(),
|
||||||
need_realloc: Cell::new(false),
|
need_realloc: Cell::new(false),
|
||||||
realloc_scheduled: Cell::new(false),
|
realloc_scheduled: Cell::new(false),
|
||||||
|
latch_listener: EventListener::new(slf.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn schedule_toplevel_screencast(self: &Rc<Self>) {
|
fn schedule_toplevel_screencast(self: &Rc<Self>) {
|
||||||
if !self.running.get() {
|
if !self.running.get() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -319,6 +328,7 @@ impl JayScreencast {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detach(&self) {
|
fn detach(&self) {
|
||||||
|
self.latch_listener.detach();
|
||||||
if let Some(target) = self.target.take() {
|
if let Some(target) = self.target.take() {
|
||||||
match target {
|
match target {
|
||||||
Target::Output(output) => {
|
Target::Output(output) => {
|
||||||
|
|
@ -427,6 +437,18 @@ impl JayScreencast {
|
||||||
self.client.state.damage(rect);
|
self.client.state.damage(rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_latch_listener(&self) {
|
||||||
|
let Some(Target::Toplevel(tl)) = self.target.get() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let data = tl.tl_data();
|
||||||
|
if data.visible.get() {
|
||||||
|
self.latch_listener.attach(&data.output().latch_event);
|
||||||
|
} else {
|
||||||
|
self.latch_listener.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JayScreencastRequestHandler for JayScreencast {
|
impl JayScreencastRequestHandler for JayScreencast {
|
||||||
|
|
@ -540,6 +562,9 @@ impl JayScreencastRequestHandler for JayScreencast {
|
||||||
let data = t.tl_data();
|
let data = t.tl_data();
|
||||||
data.jay_screencasts
|
data.jay_screencasts
|
||||||
.set((self.client.id, self.id), slf.clone());
|
.set((self.client.id, self.id), slf.clone());
|
||||||
|
if data.visible.get() {
|
||||||
|
self.latch_listener.attach(&data.output().latch_event);
|
||||||
|
}
|
||||||
new_target = Some(Target::Toplevel(t));
|
new_target = Some(Target::Toplevel(t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -360,11 +360,6 @@ impl Renderer<'_> {
|
||||||
bounds: Option<&Rect>,
|
bounds: Option<&Rect>,
|
||||||
render_highlight: bool,
|
render_highlight: bool,
|
||||||
) {
|
) {
|
||||||
if self.result.is_some() {
|
|
||||||
for screencast in tl_data.jay_screencasts.lock().values() {
|
|
||||||
screencast.schedule_toplevel_screencast();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if render_highlight {
|
if render_highlight {
|
||||||
self.render_highlight(tl_data, bounds);
|
self.render_highlight(tl_data, bounds);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,7 @@ impl ConnectorHandler {
|
||||||
screencopies: Default::default(),
|
screencopies: Default::default(),
|
||||||
title_visible: Default::default(),
|
title_visible: Default::default(),
|
||||||
schedule,
|
schedule,
|
||||||
|
latch_event: Default::default(),
|
||||||
});
|
});
|
||||||
on.update_visible();
|
on.update_visible();
|
||||||
on.update_rects();
|
on.update_rects();
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ use {
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
||||||
hash_map_ext::HashMapExt, linkedlist::LinkedList, scroller::Scroller,
|
event_listener::EventSource, hash_map_ext::HashMapExt, linkedlist::LinkedList,
|
||||||
transform_ext::TransformExt,
|
scroller::Scroller, transform_ext::TransformExt,
|
||||||
},
|
},
|
||||||
wire::{JayOutputId, JayScreencastId, ZwlrScreencopyFrameV1Id},
|
wire::{JayOutputId, JayScreencastId, ZwlrScreencopyFrameV1Id},
|
||||||
},
|
},
|
||||||
|
|
@ -80,6 +80,11 @@ pub struct OutputNode {
|
||||||
pub screencopies: CopyHashMap<(ClientId, ZwlrScreencopyFrameV1Id), Rc<ZwlrScreencopyFrameV1>>,
|
pub screencopies: CopyHashMap<(ClientId, ZwlrScreencopyFrameV1Id), Rc<ZwlrScreencopyFrameV1>>,
|
||||||
pub title_visible: Cell<bool>,
|
pub title_visible: Cell<bool>,
|
||||||
pub schedule: Rc<OutputSchedule>,
|
pub schedule: Rc<OutputSchedule>,
|
||||||
|
pub latch_event: EventSource<dyn LatchListener>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LatchListener {
|
||||||
|
fn after_latch(self: Rc<Self>);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
|
@ -148,6 +153,9 @@ impl OutputNode {
|
||||||
y_off: i32,
|
y_off: i32,
|
||||||
size: Option<(i32, i32)>,
|
size: Option<(i32, i32)>,
|
||||||
) {
|
) {
|
||||||
|
for listener in self.latch_event.iter() {
|
||||||
|
listener.after_latch();
|
||||||
|
}
|
||||||
if let Some(workspace) = self.workspace.get() {
|
if let Some(workspace) = self.workspace.get() {
|
||||||
if !workspace.may_capture.get() {
|
if !workspace.may_capture.get() {
|
||||||
return;
|
return;
|
||||||
|
|
@ -436,7 +444,9 @@ impl OutputNode {
|
||||||
|
|
||||||
pub fn ensure_workspace(self: &Rc<Self>) -> Rc<WorkspaceNode> {
|
pub fn ensure_workspace(self: &Rc<Self>) -> Rc<WorkspaceNode> {
|
||||||
if let Some(ws) = self.workspace.get() {
|
if let Some(ws) = self.workspace.get() {
|
||||||
return ws;
|
if !ws.is_dummy {
|
||||||
|
return ws;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let name = 'name: {
|
let name = 'name: {
|
||||||
for i in 1.. {
|
for i in 1.. {
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ pub trait ToplevelNode: ToplevelNodeBase {
|
||||||
fn tl_set_parent(&self, parent: Rc<dyn ContainingNode>);
|
fn tl_set_parent(&self, parent: Rc<dyn ContainingNode>);
|
||||||
fn tl_extents_changed(&self);
|
fn tl_extents_changed(&self);
|
||||||
fn tl_set_workspace(&self, ws: &Rc<WorkspaceNode>);
|
fn tl_set_workspace(&self, ws: &Rc<WorkspaceNode>);
|
||||||
|
fn tl_workspace_output_changed(&self);
|
||||||
fn tl_change_extents(self: Rc<Self>, rect: &Rect);
|
fn tl_change_extents(self: Rc<Self>, rect: &Rect);
|
||||||
fn tl_set_visible(&self, visible: bool);
|
fn tl_set_visible(&self, visible: bool);
|
||||||
fn tl_destroy(&self);
|
fn tl_destroy(&self);
|
||||||
|
|
@ -112,8 +113,20 @@ impl<T: ToplevelNodeBase> ToplevelNode for T {
|
||||||
|
|
||||||
fn tl_set_workspace(&self, ws: &Rc<WorkspaceNode>) {
|
fn tl_set_workspace(&self, ws: &Rc<WorkspaceNode>) {
|
||||||
let data = self.tl_data();
|
let data = self.tl_data();
|
||||||
data.workspace.set(Some(ws.clone()));
|
let prev = data.workspace.set(Some(ws.clone()));
|
||||||
self.tl_set_workspace_ext(ws);
|
self.tl_set_workspace_ext(ws);
|
||||||
|
let prev_id = prev.map(|p| p.output.get().id);
|
||||||
|
let new_id = Some(ws.output.get().id);
|
||||||
|
if prev_id != new_id {
|
||||||
|
self.tl_workspace_output_changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tl_workspace_output_changed(&self) {
|
||||||
|
let data = self.tl_data();
|
||||||
|
for sc in data.jay_screencasts.lock().values() {
|
||||||
|
sc.update_latch_listener();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tl_change_extents(self: Rc<Self>, rect: &Rect) {
|
fn tl_change_extents(self: Rc<Self>, rect: &Rect) {
|
||||||
|
|
@ -484,6 +497,9 @@ impl ToplevelData {
|
||||||
pub fn set_visible(&self, node: &dyn Node, visible: bool) {
|
pub fn set_visible(&self, node: &dyn Node, visible: bool) {
|
||||||
self.visible.set(visible);
|
self.visible.set(visible);
|
||||||
self.seat_state.set_visible(node, visible);
|
self.seat_state.set_visible(node, visible);
|
||||||
|
for sc in self.jay_screencasts.lock().values() {
|
||||||
|
sc.update_latch_listener();
|
||||||
|
}
|
||||||
if !visible {
|
if !visible {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -508,4 +524,11 @@ impl ToplevelData {
|
||||||
parent.cnode_child_attention_request_changed(node, true);
|
parent.cnode_child_attention_request_changed(node, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn output(&self) -> Rc<OutputNode> {
|
||||||
|
match self.workspace.get() {
|
||||||
|
None => self.state.dummy_output.get().unwrap(),
|
||||||
|
Some(ws) => ws.output.get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@ use {
|
||||||
jay_workspace::JayWorkspace,
|
jay_workspace::JayWorkspace,
|
||||||
wl_output::OutputId,
|
wl_output::OutputId,
|
||||||
wl_seat::{tablet::TabletTool, NodeSeatState, WlSeatGlobal},
|
wl_seat::{tablet::TabletTool, NodeSeatState, WlSeatGlobal},
|
||||||
wl_surface::WlSurface,
|
wl_surface::{
|
||||||
|
x_surface::xwindow::Xwindow, xdg_surface::xdg_toplevel::XdgToplevel, WlSurface,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
|
|
@ -16,7 +18,7 @@ use {
|
||||||
tree::{
|
tree::{
|
||||||
container::ContainerNode, walker::NodeVisitor, ContainingNode, Direction,
|
container::ContainerNode, walker::NodeVisitor, ContainingNode, Direction,
|
||||||
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeVisitorBase, OutputNode,
|
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeVisitorBase, OutputNode,
|
||||||
StackedNode, ToplevelNode,
|
PlaceholderNode, StackedNode, ToplevelNode,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
|
|
@ -102,6 +104,26 @@ impl WorkspaceNode {
|
||||||
fn visit_surface(&mut self, node: &Rc<WlSurface>) {
|
fn visit_surface(&mut self, node: &Rc<WlSurface>) {
|
||||||
node.set_output(self.0);
|
node.set_output(self.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
|
||||||
|
node.tl_workspace_output_changed();
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_toplevel(&mut self, node: &Rc<XdgToplevel>) {
|
||||||
|
node.tl_workspace_output_changed();
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_xwindow(&mut self, node: &Rc<Xwindow>) {
|
||||||
|
node.tl_workspace_output_changed();
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_placeholder(&mut self, node: &Rc<PlaceholderNode>) {
|
||||||
|
node.tl_workspace_output_changed();
|
||||||
|
node.node_visit_children(self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let mut visitor = OutputSetter(output);
|
let mut visitor = OutputSetter(output);
|
||||||
self.node_visit_children(&mut visitor);
|
self.node_visit_children(&mut visitor);
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ pub mod copyhashmap;
|
||||||
pub mod debug_fn;
|
pub mod debug_fn;
|
||||||
pub mod double_click_state;
|
pub mod double_click_state;
|
||||||
pub mod errorfmt;
|
pub mod errorfmt;
|
||||||
|
pub mod event_listener;
|
||||||
pub mod fdcloser;
|
pub mod fdcloser;
|
||||||
pub mod gfx_api_ext;
|
pub mod gfx_api_ext;
|
||||||
pub mod hash_map_ext;
|
pub mod hash_map_ext;
|
||||||
|
|
|
||||||
69
src/utils/event_listener.rs
Normal file
69
src/utils/event_listener.rs
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
use {
|
||||||
|
crate::utils::linkedlist::{LinkedList, LinkedListIter, LinkedNode},
|
||||||
|
std::{
|
||||||
|
cell::Cell,
|
||||||
|
rc::{Rc, Weak},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct EventSource<T: ?Sized> {
|
||||||
|
listeners: LinkedList<Weak<T>>,
|
||||||
|
on_attach: Cell<Option<Box<dyn FnOnce()>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EventListener<T: ?Sized> {
|
||||||
|
link: LinkedNode<Weak<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized> Default for EventSource<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
listeners: Default::default(),
|
||||||
|
on_attach: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized> EventSource<T> {
|
||||||
|
pub fn iter(&self) -> EventSourceIter<T> {
|
||||||
|
EventSourceIter {
|
||||||
|
iter: self.listeners.iter(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EventSourceIter<T: ?Sized> {
|
||||||
|
iter: LinkedListIter<Weak<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized> Iterator for EventSourceIter<T> {
|
||||||
|
type Item = Rc<T>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
for weak in self.iter.by_ref() {
|
||||||
|
if let Some(t) = weak.upgrade() {
|
||||||
|
return Some(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized> EventListener<T> {
|
||||||
|
pub fn new(t: Weak<T>) -> Self {
|
||||||
|
Self {
|
||||||
|
link: LinkedNode::detached(t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn attach(&self, source: &EventSource<T>) {
|
||||||
|
source.listeners.add_last_existing(&self.link);
|
||||||
|
if let Some(on_attach) = source.on_attach.take() {
|
||||||
|
on_attach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn detach(&self) {
|
||||||
|
self.link.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use {
|
use {
|
||||||
crate::utils::{numcell::NumCell, ptr_ext::PtrExt},
|
crate::utils::numcell::NumCell,
|
||||||
std::{
|
std::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
fmt::{Debug, Formatter},
|
fmt::{Debug, Formatter},
|
||||||
|
|
@ -29,20 +29,8 @@ impl<T> Default for LinkedList<T> {
|
||||||
|
|
||||||
impl<T> LinkedList<T> {
|
impl<T> LinkedList<T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let node = Box::into_raw(Box::new(NodeData {
|
Self {
|
||||||
rc: NumCell::new(LINKED_NODE_REF_COUNT),
|
root: LinkedNode::new(None),
|
||||||
prev: Cell::new(NonNull::dangling()),
|
|
||||||
next: Cell::new(NonNull::dangling()),
|
|
||||||
data: None,
|
|
||||||
}));
|
|
||||||
unsafe {
|
|
||||||
node.deref().prev.set(NonNull::new_unchecked(node));
|
|
||||||
node.deref().next.set(NonNull::new_unchecked(node));
|
|
||||||
Self {
|
|
||||||
root: LinkedNode {
|
|
||||||
data: NonNull::new_unchecked(node),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -290,12 +278,14 @@ impl<T> NodeRef<T> {
|
||||||
self.peer(|d| &d.next)
|
self.peer(|d| &d.next)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn detach(&self) {
|
pub fn detach(&self) {
|
||||||
let data = self.data.as_ref();
|
unsafe {
|
||||||
data.prev.get().as_ref().next.set(data.next.get());
|
let data = self.data.as_ref();
|
||||||
data.next.get().as_ref().prev.set(data.prev.get());
|
data.prev.get().as_ref().next.set(data.next.get());
|
||||||
data.prev.set(self.data);
|
data.next.get().as_ref().prev.set(data.prev.get());
|
||||||
data.next.set(self.data);
|
data.prev.set(self.data);
|
||||||
|
data.next.set(self.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -322,6 +312,23 @@ impl<T> Drop for LinkedNode<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> LinkedNode<T> {
|
impl<T> LinkedNode<T> {
|
||||||
|
fn new(t: Option<T>) -> Self {
|
||||||
|
let node = Box::leak(Box::new(NodeData {
|
||||||
|
rc: NumCell::new(LINKED_NODE_REF_COUNT),
|
||||||
|
prev: Cell::new(NonNull::dangling()),
|
||||||
|
next: Cell::new(NonNull::dangling()),
|
||||||
|
data: t,
|
||||||
|
}));
|
||||||
|
let ptr = NonNull::from(&mut *node);
|
||||||
|
node.prev.set(ptr);
|
||||||
|
node.next.set(ptr);
|
||||||
|
LinkedNode { data: node.into() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn detached(t: T) -> Self {
|
||||||
|
Self::new(Some(t))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_ref(&self) -> NodeRef<T> {
|
pub fn to_ref(&self) -> NodeRef<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.data.as_ref().rc.fetch_add(1);
|
self.data.as_ref().rc.fetch_add(1);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue