1
0
Fork 0
forked from wry/wry

autocommit 2022-04-08 23:02:38 CEST

This commit is contained in:
Julian Orth 2022-04-08 23:02:38 +02:00
parent 0bd9a70e69
commit 21e2216ce5
40 changed files with 587 additions and 255 deletions

View file

@ -21,6 +21,7 @@ use jay_config::{
Command,
Direction::{Down, Left, Right, Up},
};
use jay_config::keyboard::syms::SYM_c;
const MOD: Modifiers = ALT;
@ -44,6 +45,8 @@ fn configure_seat(s: Seat) {
s.bind(MOD | SYM_f, move || s.focus_parent());
s.bind(MOD | SHIFT | SYM_c, move || s.close());
s.bind(MOD | SHIFT | SYM_f, move || s.toggle_floating());
s.bind(SYM_Super_L, || Command::new("alacritty").spawn());

View file

@ -296,6 +296,10 @@ impl Client {
self.send(&ClientMessage::CreateSplit { seat, axis });
}
pub fn close(&self, seat: Seat) {
self.send(&ClientMessage::Close { seat });
}
pub fn focus_parent(&self, seat: Seat) {
self.send(&ClientMessage::FocusParent { seat });
}

View file

@ -146,6 +146,9 @@ pub enum ClientMessage<'a> {
seat: Seat,
axis: Axis,
},
Close {
seat: Seat,
},
FocusParent {
seat: Seat,
},

View file

@ -117,6 +117,10 @@ impl Seat {
get!().focus_parent(self);
}
pub fn close(self) {
get!().close(self);
}
pub fn toggle_floating(self) {
get!().toggle_floating(self);
}

View file

@ -25,6 +25,7 @@ pub enum LogLevel {
#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq)]
pub enum Direction {
Unspecified,
Left,
Down,
Up,

View file

@ -1,5 +1,5 @@
use {
crate::{video::drm::ConnectorType, fixed::Fixed},
crate::{fixed::Fixed, video::drm::ConnectorType},
std::{
fmt::{Debug, Display, Formatter},
rc::Rc,

View file

@ -11,7 +11,6 @@ use {
},
backends::metal::video::{MetalDrmDevice, PendingDrmDevice},
dbus::DbusError,
video::{drm::DrmError, gbm::GbmError},
libinput::{
consts::{
AccelProfile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
@ -35,6 +34,7 @@ use {
smallmap::SmallMap,
syncqueue::SyncQueue,
},
video::{drm::DrmError, gbm::GbmError},
},
std::{
cell::{Cell, RefCell},

View file

@ -7,9 +7,9 @@ use {
MetalBackend, MetalDevice, MetalError, MetalInputDevice,
},
dbus::TRUE,
video::drm::DrmMaster,
udev::UdevDevice,
utils::{errorfmt::ErrorFmt, nonblock::set_nonblock},
video::drm::DrmMaster,
wire_dbus::org::freedesktop::login1::session::{PauseDevice, ResumeDevice},
},
bstr::ByteSlice,

View file

@ -5,6 +5,14 @@ use {
BackendEvent, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, MonitorInfo,
},
backends::metal::{DrmId, MetalBackend, MetalError},
edid::Descriptor,
format::{Format, XRGB8888},
render::{Framebuffer, RenderContext},
state::State,
utils::{
bitflags::BitflagsExt, clonecell::CloneCell, debug_fn::debug_fn, errorfmt::ErrorFmt,
numcell::NumCell, oserror::OsError, syncqueue::SyncQueue,
},
video::{
drm::{
drm_mode_modeinfo, Change, ConnectorStatus, ConnectorType, DrmBlob, DrmConnector,
@ -16,14 +24,6 @@ use {
gbm::{GbmDevice, GBM_BO_USE_RENDERING, GBM_BO_USE_SCANOUT},
ModifiedFormat, INVALID_MODIFIER,
},
edid::Descriptor,
format::{Format, XRGB8888},
render::{Framebuffer, RenderContext},
state::State,
utils::{
bitflags::BitflagsExt, clonecell::CloneCell, debug_fn::debug_fn, errorfmt::ErrorFmt,
numcell::NumCell, oserror::OsError, syncqueue::SyncQueue,
},
},
ahash::{AHashMap, AHashSet},
bstr::{BString, ByteSlice},
@ -280,10 +280,10 @@ fn create_connector(
if let Some(d) = descriptor {
match d {
Descriptor::DisplayProductSerialNumber(s) => {
serial_number = s.to_string();
serial_number = s.clone();
}
Descriptor::DisplayProductName(s) => {
name = s.to_string();
name = s.clone();
}
_ => {}
}

View file

@ -6,11 +6,6 @@ use {
InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent,
KeyState, Mode, MonitorInfo, ScrollAxis,
},
video::{
drm::{ConnectorType, Drm, DrmError},
gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING},
ModifiedFormat, INVALID_MODIFIER,
},
fixed::Fixed,
format::XRGB8888,
render::{Framebuffer, RenderContext, RenderError},
@ -19,6 +14,11 @@ use {
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell,
queue::AsyncQueue, syncqueue::SyncQueue,
},
video::{
drm::{ConnectorType, Drm, DrmError},
gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING},
ModifiedFormat, INVALID_MODIFIER,
},
wire_xcon::{
ChangeProperty, ChangeWindowAttributes, ConfigureNotify, CreateCursor, CreatePixmap,
CreateWindow, CreateWindowValues, DestroyNotify, Dri3Open, Dri3PixmapFromBuffer,

View file

@ -132,6 +132,12 @@ impl ConfigProxyHandler {
Ok(())
}
fn handle_close(&self, seat: Seat) -> Result<(), CphError> {
let seat = self.get_seat(seat)?;
seat.close();
Ok(())
}
fn handle_focus(&self, seat: Seat, direction: Direction) -> Result<(), CphError> {
let seat = self.get_seat(seat)?;
seat.move_focus(direction);
@ -763,6 +769,9 @@ impl ConfigProxyHandler {
ClientMessage::ConnectorSetPosition { connector, x, y } => self
.handle_connector_set_position(connector, x, y)
.wrn("connector_set_position")?,
ClientMessage::Close { seat } => self
.handle_close(seat)
.wrn("close")?,
}
Ok(())
}

View file

@ -347,9 +347,9 @@ pub struct DetailedTimingDescriptor {
pub enum Descriptor {
Unknown(u8),
DetailedTimingDescriptor(DetailedTimingDescriptor),
DisplayProductSerialNumber(BString),
AlphanumericDataString(BString),
DisplayProductName(BString),
DisplayProductSerialNumber(String),
AlphanumericDataString(String),
DisplayProductName(String),
DisplayRangeLimitsAndAdditionalTiming(DisplayRangeLimitsAndAdditionalTiming),
EstablishedTimings3(EstablishedTimings3),
ColorManagementData(ColorManagementData),
@ -880,11 +880,15 @@ impl<'a> EdidParser<'a> {
let _ctx = self.push_ctx(EdidParseContext::Descriptor);
let b = self.read_n::<18>()?;
let str = || {
let s = &b[5..];
match s.find_byte(b'\n') {
Some(n) => s[..n].as_bstr().to_owned(),
_ => s.as_bstr().to_owned(),
let mut s = &b[5..];
if let Some(n) = s.find_byte(b'\n') {
s = &s[..n];
};
let mut res = String::new();
for &b in s {
res.push_str(CP437[b as usize]);
}
res
};
let res = if (b[0], b[1]) == (0, 0) {
match b[3] {
@ -1079,3 +1083,20 @@ pub fn parse(data: &[u8]) -> Result<EdidFile, EdidError> {
};
parser.parse()
}
const CP437: &[&str] = &[
"\u{0}", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "§", "", "", "", "", "", "", "", "", "", "", " ", "!", "\"", "#", "$",
"%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]",
"^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p",
"q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "", "Ç", "ü", "é", "â",
"ä", "à", "å", "ç", "ê", "ë", "è", "ï", "î", "ì", "Ä", "Å", "É", "æ", "Æ", "ô", "ö", "ò", "û",
"ù", "ÿ", "Ö", "Ü", "¢", "£", "¥", "", "ƒ", "á", "í", "ó", "ú", "ñ", "Ñ", "ª", "º", "¿", "",
"¬", "½", "¼", "¡", "«", "»", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "α", "ß", "Γ",
"π", "Σ", "σ", "µ", "τ", "Φ", "Θ", "Ω", "δ", "", "φ", "ε", "", "", "±", "", "", "", "",
"÷", "", "°", "", "·", "", "", "²", "", "\u{a0}",
];

View file

@ -1,16 +1,16 @@
use {
crate::{
client::{Client, ClientError},
video::{
dma::{DmaBuf, DmaBufPlane},
INVALID_MODIFIER,
},
globals::{Global, GlobalName},
ifs::wl_buffer::WlBuffer,
leaks::Tracker,
object::Object,
render::RenderError,
utils::buffd::{MsgParser, MsgParserError},
video::{
dma::{DmaBuf, DmaBufPlane},
INVALID_MODIFIER,
},
wire::{wl_drm::*, WlDrmId},
},
bstr::ByteSlice,

View file

@ -274,6 +274,11 @@ impl WlSeatGlobal {
}
}
pub fn close(self: &Rc<Self>) {
let kb_node = self.keyboard_node.get();
kb_node.close();
}
pub fn move_focus(self: &Rc<Self>, direction: Direction) {
let kb_node = self.keyboard_node.get();
kb_node.move_focus(self, direction);

View file

@ -81,16 +81,32 @@ impl NodeSeatState {
}
pub fn release_kb_focus(&self) {
self.release_kb_focus2(true);
}
fn release_kb_focus2(&self, focus_last: bool) {
while let Some((_, seat)) = self.kb_foci.pop() {
seat.ungrab_kb();
seat.keyboard_node.set(seat.state.root.clone());
if let Some(tl) = seat.toplevel_focus_history.last() {
seat.focus_node(tl.focus_surface(seat.id));
if focus_last {
if let Some(tl) = seat.toplevel_focus_history.last() {
seat.focus_node(tl.focus_surface(seat.id));
}
}
}
}
pub fn for_each_kb_focus<F: FnMut(Rc<WlSeatGlobal>)>(&self, mut f: F) {
self.kb_foci.iter().for_each(|(_, s)| f(s));
}
pub fn destroy_node(&self, node: &dyn Node) {
self.destroy_node2(node, true);
}
fn destroy_node2(&self, node: &dyn Node, focus_last: bool) {
// NOTE: Also called by set_visible(false)
while let Some((_, seat)) = self.grabs.pop() {
seat.pointer_owner.revert_to_default(&seat);
}
@ -109,7 +125,16 @@ impl NodeSeatState {
}
seat.state.tree_changed();
}
self.release_kb_focus();
self.release_kb_focus2(focus_last);
}
pub fn set_visible(&self, node: &dyn Node, visible: bool) {
if !visible {
if !self.kb_foci.is_empty() {
node.active_changed(false);
}
self.destroy_node2(node, false);
}
}
}

View file

@ -84,6 +84,7 @@ pub struct WlSurface {
pub id: WlSurfaceId,
pub node_id: SurfaceNodeId,
pub client: Rc<Client>,
visible: Cell<bool>,
role: Cell<SurfaceRole>,
pending: PendingState,
input_region: Cell<Option<Rc<Region>>>,
@ -199,6 +200,7 @@ impl WlSurface {
id,
node_id: client.state.node_ids.next(),
client: client.clone(),
visible: Cell::new(false),
role: Cell::new(SurfaceRole::None),
pending: Default::default(),
input_region: Cell::new(None),
@ -624,6 +626,27 @@ impl Node for WlSurface {
self.node_id.into()
}
fn close(&self) {
if let Some(tl) = self.toplevel.get() {
tl.close();
}
}
fn visible(&self) -> bool {
self.visible.get()
}
fn set_visible(&self, visible: bool) {
self.visible.set(visible);
let children = self.children.borrow_mut();
if let Some(children) = children.deref() {
for child in children.subsurfaces.values() {
child.surface.set_visible(visible);
}
}
self.seat_state.set_visible(self, visible);
}
fn seat_state(&self) -> &NodeSeatState {
&self.seat_state
}

View file

@ -288,6 +288,15 @@ impl Node for XdgPopup {
visitor.visit_surface(&self.xdg.surface);
}
fn visible(&self) -> bool {
self.xdg.surface.visible.get()
}
fn set_visible(&self, visible: bool) {
self.xdg.surface.set_visible(visible);
self.xdg.seat_state.set_visible(self, visible);
}
fn get_workspace(&self) -> Option<Rc<WorkspaceNode>> {
self.xdg.workspace.get()
}

View file

@ -143,6 +143,12 @@ impl XdgToplevel {
self.send_configure(width, height)
}
fn send_close(&self) {
self.xdg.surface.client.event(Close {
self_id: self.id,
});
}
fn send_configure(&self, width: i32, height: i32) {
let states: Vec<_> = self.states.borrow().iter().copied().collect();
self.xdg.surface.client.event(Configure {
@ -384,6 +390,15 @@ impl Node for XdgToplevel {
visitor.visit_surface(&self.xdg.surface);
}
fn visible(&self) -> bool {
self.xdg.surface.visible.get()
}
fn set_visible(&self, visible: bool) {
self.xdg.surface.set_visible(visible);
self.xdg.seat_state.set_visible(self, visible);
}
fn get_workspace(&self) -> Option<Rc<WorkspaceNode>> {
self.xdg.workspace.get()
}
@ -508,6 +523,10 @@ impl ToplevelNode for XdgToplevel {
self.map_floating(&ws);
}
}
fn close(&self) {
self.send_close();
}
}
impl XdgSurfaceExt for XdgToplevel {
@ -546,12 +565,12 @@ impl XdgSurfaceExt for XdgToplevel {
}
}
}
{
let seats = surface.client.state.globals.lock_seats();
for seat in seats.values() {
seat.focus_toplevel(self.clone());
}
}
// {
// let seats = surface.client.state.globals.lock_seats();
// for seat in seats.values() {
// seat.focus_toplevel(self.clone());
// }
// }
surface.client.state.tree_changed();
}
}

View file

@ -1,4 +1,3 @@
use std::ops::Not;
use {
crate::{
client::Client,
@ -27,7 +26,7 @@ use {
jay_config::Direction,
std::{
cell::{Cell, RefCell},
ops::{Deref},
ops::{Deref, Not},
rc::Rc,
},
thiserror::Error,
@ -142,7 +141,6 @@ pub struct Xwindow {
pub events: Rc<AsyncQueue<XWaylandEvent>>,
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
pub display_link: RefCell<Option<LinkedNode<Rc<dyn Node>>>>,
pub display_xlink: RefCell<Option<LinkedNode<Rc<Xwindow>>>>,
pub toplevel_data: ToplevelData,
}
@ -219,7 +217,6 @@ impl Xwindow {
events: events.clone(),
workspace: Default::default(),
display_link: Default::default(),
display_xlink: Default::default(),
toplevel_data: Default::default(),
}
}
@ -279,8 +276,6 @@ impl Xwindow {
Change::Map if self.data.info.override_redirect.get() => {
*self.display_link.borrow_mut() =
Some(self.data.state.root.stacked.add_last(self.clone()));
*self.display_xlink.borrow_mut() =
Some(self.data.state.root.xstacked.add_last(self.clone()));
self.data.state.tree_changed();
}
Change::Map if self.data.info.wants_floating.get() => {
@ -334,13 +329,21 @@ impl Node for Xwindow {
self.id.into()
}
fn visible(&self) -> bool {
self.surface.visible.get()
}
fn set_visible(&self, visible: bool) {
self.surface.set_visible(visible);
self.seat_state.set_visible(self, visible);
}
fn seat_state(&self) -> &NodeSeatState {
&self.seat_state
}
fn destroy_node(&self, _detach: bool) {
self.toplevel_data.clear();
self.display_xlink.borrow_mut().take();
self.display_link.borrow_mut().take();
self.workspace.take();
self.focus_history.clear();
@ -449,7 +452,8 @@ impl ToplevelNode for Xwindow {
}
fn accepts_keyboard_focus(&self) -> bool {
self.data.info.never_focus.get().not() && self.data.info.input_model.get() != XInputModel::None
self.data.info.never_focus.get().not()
&& self.data.info.input_model.get() != XInputModel::None
}
fn default_surface(&self) -> Rc<WlSurface> {
@ -482,6 +486,10 @@ impl ToplevelNode for Xwindow {
.map_floating(self.clone(), extents.width(), extents.height(), &ws);
}
}
fn close(&self) {
self.events.push(XWaylandEvent::Close(self.data.clone()));
}
}
#[derive(Debug, Error)]

View file

@ -370,6 +370,10 @@ impl Node for ZwlrLayerSurfaceV1 {
self.surface.clone().visit(visitor);
}
fn visible(&self) -> bool {
true
}
fn absolute_position(&self) -> Rect {
self.pos.get()
}

View file

@ -1,10 +1,6 @@
use {
crate::{
client::ClientError,
video::{
dma::{DmaBuf, DmaBufPlane},
INVALID_MODIFIER,
},
ifs::{wl_buffer::WlBuffer, zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1},
leaks::Tracker,
object::Object,
@ -13,6 +9,10 @@ use {
buffd::{MsgParser, MsgParserError},
errorfmt::ErrorFmt,
},
video::{
dma::{DmaBuf, DmaBufPlane},
INVALID_MODIFIER,
},
wire::{zwp_linux_buffer_params_v1::*, WlBufferId, ZwpLinuxBufferParamsV1Id},
},
ahash::AHashMap,

View file

@ -1,12 +1,12 @@
use {
crate::{
client::{Client, ClientError},
video::INVALID_MODIFIER,
globals::{Global, GlobalName},
ifs::zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1,
leaks::Tracker,
object::Object,
utils::buffd::{MsgParser, MsgParserError},
video::INVALID_MODIFIER,
wire::{zwp_linux_dmabuf_v1::*, ZwpLinuxDmabufV1Id},
},
std::rc::Rc,

View file

@ -45,7 +45,6 @@ mod compositor;
mod config;
mod cursor;
mod dbus;
mod video;
mod edid;
mod event_loop;
mod fixed;
@ -70,6 +69,7 @@ mod tools;
mod tree;
mod udev;
mod utils;
mod video;
mod wheel;
mod wire;
mod wire_dbus;

View file

@ -1,6 +1,5 @@
use {
crate::{
video::{dma::DmaBuf, drm::Drm, gbm::GbmDevice, INVALID_MODIFIER},
format::{formats, Format},
render::{
egl::{
@ -27,6 +26,7 @@ use {
sys::{eglInitialize, EGL_PLATFORM_GBM_KHR},
RenderError,
},
video::{dma::DmaBuf, drm::Drm, gbm::GbmDevice, INVALID_MODIFIER},
},
ahash::AHashMap,
std::{ptr, rc::Rc},

View file

@ -1,9 +1,5 @@
use {
crate::{
video::{
dma::DmaBuf,
drm::{Drm, NodeType},
},
format::{Format, XRGB8888},
render::{
egl::{context::EglContext, display::EglDisplay},
@ -13,6 +9,10 @@ use {
renderer::{framebuffer::Framebuffer, image::Image},
RenderError, Texture,
},
video::{
dma::DmaBuf,
drm::{Drm, NodeType},
},
},
ahash::AHashMap,
std::{

View file

@ -25,7 +25,7 @@ use {
},
state::State,
theme::Color,
tree::{ContainerNode, FloatNode, Node, OutputNode, WorkspaceNode},
tree::{ContainerNode, FloatNode, OutputNode, WorkspaceNode},
utils::rc_eq::rc_eq,
},
std::{ops::Deref, rc::Rc},
@ -70,23 +70,14 @@ impl Renderer<'_> {
self.render_workspace(&ws, x, y + th);
}
for stacked in self.state.root.stacked.iter() {
if let Some(ws) = stacked.get_workspace() {
if ws.visible.get() {
let pos = stacked.absolute_position();
if pos.intersects(&opos) {
let (x, y) = opos.translate(pos.x1(), pos.y1());
stacked.render(self, x, y);
}
if stacked.visible() {
let pos = stacked.absolute_position();
if pos.intersects(&opos) {
let (x, y) = opos.translate(pos.x1(), pos.y1());
stacked.render(self, x, y);
}
}
}
for stacked in self.state.root.xstacked.iter() {
let pos = stacked.absolute_position();
if pos.intersects(&opos) {
let (x, y) = opos.translate(pos.x1(), pos.y1());
stacked.render(self, x, y);
}
}
render_layer!(output.layers[2]);
render_layer!(output.layers[3]);
}

View file

@ -74,6 +74,11 @@ pub trait Node {
fn destroy_node(&self, detach: bool);
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor);
fn visit_children(&self, visitor: &mut dyn NodeVisitor);
fn visible(&self) -> bool;
fn set_visible(&self, visible: bool) {
let _ = visible;
}
fn get_workspace(&self) -> Option<Rc<WorkspaceNode>> {
None
@ -134,6 +139,10 @@ pub trait Node {
let _ = direction;
}
fn close(&self) {
// nothing
}
fn move_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, direction: Direction) {
let _ = seat;
let _ = direction;
@ -144,7 +153,7 @@ pub trait Node {
}
fn move_focus_from_child(
&self,
self: Rc<Self>,
seat: &Rc<WlSeatGlobal>,
child: &dyn Node,
direction: Direction,

View file

@ -31,6 +31,8 @@ use {
rc::Rc,
},
};
use crate::tree::{generic_node_visitor};
use crate::utils::smallmap::SmallMap;
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -102,12 +104,14 @@ pub struct ContainerNode {
compute_render_data_scheduled: Cell<bool>,
num_children: NumCell<usize>,
pub children: LinkedList<ContainerChild>,
focus_history: LinkedList<NodeRef<ContainerChild>>,
child_nodes: RefCell<AHashMap<NodeId, LinkedNode<ContainerChild>>>,
seat_state: NodeSeatState,
workspace: CloneCell<Rc<WorkspaceNode>>,
seats: RefCell<AHashMap<SeatId, SeatState>>,
state: Rc<State>,
pub render_data: RefCell<ContainerRenderData>,
visible: Cell<bool>,
}
impl Debug for ContainerNode {
@ -116,14 +120,17 @@ impl Debug for ContainerNode {
}
}
#[derive(Clone)]
pub struct ContainerChild {
pub node: Rc<dyn Node>,
pub active: Cell<bool>,
title: RefCell<String>,
pub title_rect: Cell<Rect>,
focus_history: Cell<Option<LinkedNode<NodeRef<ContainerChild>>>>,
// fields below only valid in tabbed layout
pub body: Cell<Rect>,
pub content: Cell<Rect>,
factor: Cell<f64>,
title: RefCell<String>,
}
struct SeatState {
@ -166,11 +173,13 @@ impl ContainerNode {
child.id(),
children.add_last(ContainerChild {
node: child.clone(),
active: Cell::new(false),
body: Cell::new(Default::default()),
content: Cell::new(Default::default()),
active: Default::default(),
body: Default::default(),
content: Default::default(),
factor: Cell::new(1.0),
title: Default::default(),
title_rect: Default::default(),
focus_history: Default::default(),
}),
);
let slf = Rc::new(Self {
@ -193,12 +202,14 @@ impl ContainerNode {
compute_render_data_scheduled: Cell::new(false),
num_children: NumCell::new(1),
children,
focus_history: Default::default(),
child_nodes: RefCell::new(child_nodes),
seat_state: Default::default(),
workspace: CloneCell::new(workspace.clone()),
seats: RefCell::new(Default::default()),
state: state.clone(),
render_data: Default::default(),
visible: Cell::new(false),
});
child.set_parent(slf.clone());
slf
@ -254,24 +265,26 @@ impl ContainerNode {
where
F: FnOnce(ContainerChild) -> LinkedNode<ContainerChild>,
{
{
let new_ref = {
let mut links = self.child_nodes.borrow_mut();
if links.contains_key(&new.id()) {
log::error!("Tried to add a child to a container that already contains the child");
return;
}
links.insert(
new.id(),
f(ContainerChild {
node: new.clone(),
active: Cell::new(false),
body: Default::default(),
content: Default::default(),
factor: Cell::new(0.0),
title: Default::default(),
}),
);
}
let link = f(ContainerChild {
node: new.clone(),
active: Default::default(),
body: Default::default(),
content: Default::default(),
factor: Default::default(),
title: Default::default(),
title_rect: Default::default(),
focus_history: Default::default(),
});
let r = link.to_ref();
links.insert( new.id(), link, );
r
};
new.clone().set_workspace(&self.workspace.get());
new.clone().set_parent(self.clone());
let num_children = self.num_children.fetch_add(1) + 1;
@ -288,6 +301,9 @@ impl ContainerNode {
sum_factors += factor;
}
self.sum_factors.set(sum_factors);
if self.mono_child.get().is_some() {
self.activate_child(&new_ref);
}
self.schedule_layout();
self.cancel_seat_ops();
}
@ -332,6 +348,25 @@ impl ContainerNode {
.change_extents(&mb.move_(self.abs_x1.get(), self.abs_y1.get()));
self.mono_content
.set(child.content.get().at_point(mb.x1(), mb.y1()));
let th = self.state.theme.title_height.get();
let bw = self.state.theme.border_width.get();
let num_children = self.num_children.get() as i32;
let content_width = self.width.get().sub(bw * (num_children - 1)).max(0);
let width_per_child = content_width / num_children;
let mut rem = content_width % num_children;
let mut pos = 0;
for child in self.children.iter() {
let mut width = width_per_child;
if rem > 0 {
width += 1;
rem -= 1;
}
child
.title_rect
.set(Rect::new_sized(pos, 0, width, th).unwrap());
pos += width + bw;
}
}
fn perform_split_layout(self: &Rc<Self>) {
@ -402,7 +437,17 @@ impl ContainerNode {
}
self.sum_factors.set(1.0);
for child in self.children.iter() {
let body = child.body.get().move_(self.abs_x1.get(), self.abs_y1.get());
let body = child.body.get();
child.title_rect.set(
Rect::new_sized(
body.x1(),
body.y1() - title_height - 1,
body.width(),
title_height,
)
.unwrap(),
);
let body = body.move_(self.abs_x1.get(), self.abs_y1.get());
child.node.clone().change_extents(&body);
child.position_content();
}
@ -567,77 +612,79 @@ impl ContainerNode {
let font = theme.font.borrow_mut();
let cwidth = self.width.get();
let cheight = self.height.get();
let num_children = self.num_children.get() as i32;
let ctx = self.state.render_ctx.get();
rd.titles.clear();
rd.title_rects.clear();
rd.active_title_rects.clear();
rd.border_rects.clear();
rd.underline_rects.clear();
let mut render_title = |title: &str, width: i32, x: i32, y: i32| {
if th == 0 || width == 0 || title.is_empty() {
return;
let mono = self.mono_child.get().is_some();
let split = self.split.get();
for (i, child) in self.children.iter().enumerate() {
let rect = child.title_rect.get();
if i > 0 {
let rect = if mono {
Rect::new_sized(rect.x1() - bw, 0, bw, th)
} else if split == ContainerSplit::Horizontal {
Rect::new_sized(rect.x1() - bw, 0, bw, cheight)
} else {
Rect::new_sized(0, rect.y1() - bw, cwidth, bw)
};
rd.border_rects.push(rect.unwrap());
}
if let Some(ctx) = &ctx {
match text::render(ctx, width, th, &font, title, Color::GREY) {
Ok(t) => rd.titles.push(ContainerTitle { x, y, tex: t }),
Err(e) => {
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
if child.active.get() {
rd.active_title_rects.push(rect);
} else {
rd.title_rects.push(rect);
}
if !mono {
let rect = Rect::new_sized(rect.x1(), rect.y2(), rect.width(), 1).unwrap();
rd.underline_rects.push(rect);
}
'render_title: {
let title = child.title.borrow_mut();
if th == 0 || rect.width() == 0 || title.is_empty() {
break 'render_title;
}
if let Some(ctx) = &ctx {
match text::render(ctx, rect.width(), th, &font, title.deref(), Color::GREY) {
Ok(t) => rd.titles.push(ContainerTitle {
x: rect.x1(),
y: rect.y1(),
tex: t,
}),
Err(e) => {
log::error!("Could not render title {}: {}", title, ErrorFmt(e));
}
}
}
}
};
if self.mono_child.get().is_some() {
let content_width = self.width.get().sub(bw * (num_children - 1)).max(0);
let space_per_child = content_width / num_children;
let mut rem = content_width % num_children;
let mut pos = 0;
for (i, c) in self.children.iter().enumerate() {
if i > 0 {
rd.border_rects
.push(Rect::new_sized(pos - bw, 0, bw, th).unwrap());
}
let mut width = space_per_child;
if rem > 0 {
rem -= 1;
width += 1;
}
let rect = Rect::new_sized(pos, 0, width, th).unwrap();
if c.active.get() {
rd.active_title_rects.push(rect);
} else {
rd.title_rects.push(rect);
}
let title = c.title.borrow_mut();
render_title(&title, width, pos, 0);
pos += width + bw;
}
}
if mono {
rd.underline_rects
.push(Rect::new_sized(0, th, cwidth, 1).unwrap());
} else {
let split = self.split.get();
for (i, c) in self.children.iter().enumerate() {
let body = c.body.get();
if i > 0 {
let rect = if split == ContainerSplit::Horizontal {
Rect::new_sized(body.x1() - bw, 0, bw, cheight).unwrap()
} else {
Rect::new_sized(0, body.y1() - th - 1 - bw, cwidth, bw).unwrap()
};
rd.border_rects.push(rect);
}
let rect =
Rect::new_sized(body.x1(), body.y1() - th - 1, body.width(), th).unwrap();
if c.active.get() {
rd.active_title_rects.push(rect);
} else {
rd.title_rects.push(rect);
}
let rect = Rect::new_sized(body.x1(), body.y1() - 1, body.width(), 1).unwrap();
rd.underline_rects.push(rect);
let title = c.title.borrow_mut();
render_title(&title, body.width(), body.x1(), body.y1() - th - 1);
}
}
fn activate_child(self: &Rc<Self>, child: &NodeRef<ContainerChild>) {
if let Some(mc) = self.mono_child.get() {
if mc.node.id() == child.node.id() {
return;
}
let seats = SmallMap::<SeatId, Rc<WlSeatGlobal>, 3>::new();
mc.node.visit_children(&mut generic_node_visitor(|node| {
node.seat_state().for_each_kb_focus(|s| {
seats.insert(s.id(), s);
});
}));
mc.node.set_visible(false);
for (_, seat) in seats.take() {
child.node.clone().do_focus(&seat, Direction::Unspecified);
}
self.mono_child.set(Some(child.clone()));
self.schedule_layout();
} else {
}
}
}
@ -676,6 +723,18 @@ impl Node for ContainerNode {
self.id.into()
}
fn visible(&self) -> bool {
self.visible.get()
}
fn set_visible(&self, visible: bool) {
self.visible.set(visible);
for child in self.children.iter() {
child.node.set_visible(visible);
}
self.seat_state.set_visible(self, visible);
}
fn seat_state(&self) -> &NodeSeatState {
&self.seat_state
}
@ -771,11 +830,16 @@ impl Node for ContainerNode {
let node = if let Some(cn) = self.mono_child.get() {
Some(cn)
} else {
match direction {
Direction::Left => self.children.last(),
Direction::Down => self.children.first(),
Direction::Up => self.children.last(),
Direction::Right => self.children.first(),
let split = self.split.get();
match (direction, split) {
(Direction::Left, ContainerSplit::Horizontal) => self.children.last(),
(Direction::Down, ContainerSplit::Vertical) => self.children.first(),
(Direction::Up, ContainerSplit::Vertical) => self.children.last(),
(Direction::Right, ContainerSplit::Horizontal) => self.children.first(),
_ => match self.focus_history.last() {
Some(n) => Some(n.deref().clone()),
None => self.children.last(),
}
}
};
if let Some(node) = node {
@ -798,7 +862,7 @@ impl Node for ContainerNode {
}
fn move_focus_from_child(
&self,
self: Rc<Self>,
seat: &Rc<WlSeatGlobal>,
child: &dyn Node,
direction: Direction,
@ -821,7 +885,7 @@ impl Node for ContainerNode {
if !in_line {
self.parent
.get()
.move_focus_from_child(seat, self, direction);
.move_focus_from_child(seat, &*self, direction);
return;
}
let prev = match direction {
@ -829,6 +893,7 @@ impl Node for ContainerNode {
Direction::Down => false,
Direction::Up => true,
Direction::Right => false,
Direction::Unspecified => true,
};
let sibling = match prev {
true => child.prev(),
@ -839,21 +904,15 @@ impl Node for ContainerNode {
None => {
self.parent
.get()
.move_focus_from_child(seat, self, direction);
.move_focus_from_child(seat, &*self, direction);
return;
}
};
if mc.is_some() {
self.mono_child.set(Some(sibling.clone()));
let body = self.mono_body.get();
self.mono_content
.set(sibling.content.get().at_point(body.x1(), body.y1()));
sibling
.node
.clone()
.change_extents(&body.move_(self.abs_x1.get(), self.abs_y1.get()));
self.activate_child(&sibling);
} else {
sibling.node.clone().do_focus(seat, direction);
}
sibling.node.clone().do_focus(seat, direction);
}
//
fn move_child(self: Rc<Self>, child: Rc<dyn Node>, direction: Direction) {
@ -882,12 +941,10 @@ impl Node for ContainerNode {
neighbor.node.clone().insert_child(child, direction);
return;
}
let cc = cc.deref().clone();
let link = match prev {
true => neighbor.prepend(cc),
false => neighbor.append(cc),
};
self.child_nodes.borrow_mut().insert(child.id(), link);
match prev {
true => neighbor.prepend_existing(&cc),
false => neighbor.append_existing(&cc),
}
self.schedule_layout();
return;
}
@ -932,7 +989,6 @@ impl Node for ContainerNode {
if button != BTN_LEFT {
return;
}
let title_height = self.state.theme.title_height.get();
let mut seat_datas = self.seats.borrow_mut();
let seat_data = match seat_datas.get_mut(&seat.id()) {
Some(s) => s,
@ -943,51 +999,38 @@ impl Node for ContainerNode {
return;
}
let (kind, child) = 'res: {
if self.mono_child.get().is_some() {
let width_per_child = self.width.get() / self.num_children.get() as i32;
let mut width_per_child_rem = self.width.get() % self.num_children.get() as i32;
let mut pos = 0;
for child in self.children.iter() {
pos += width_per_child;
if width_per_child_rem > 0 {
pos += 1;
width_per_child_rem -= 1;
}
if pos > seat_data.x {
break 'res (SeatOpKind::Move, child);
let mono = self.mono_child.get().is_some();
for child in self.children.iter() {
let rect = child.title_rect.get();
if rect.contains(seat_data.x, seat_data.y) {
self.activate_child(&child);
break 'res (SeatOpKind::Move, child);
} else if !mono {
if self.split.get() == ContainerSplit::Horizontal {
if seat_data.x < rect.x1() {
break 'res (
SeatOpKind::Resize {
dist_left: seat_data.x
- child.prev().unwrap().body.get().x2(),
dist_right: child.body.get().x1() - seat_data.x,
},
child,
);
}
} else {
if seat_data.y < rect.y1() {
break 'res (
SeatOpKind::Resize {
dist_left: seat_data.y
- child.prev().unwrap().body.get().y2(),
dist_right: child.body.get().y1() - seat_data.y,
},
child,
);
}
}
}
} else if self.split.get() == ContainerSplit::Horizontal {
for child in self.children.iter() {
let body = child.body.get();
if seat_data.x < body.x2() {
let op = if seat_data.x < body.x1() {
SeatOpKind::Resize {
dist_left: seat_data.x - child.prev().unwrap().body.get().x2(),
dist_right: body.x1() - seat_data.x,
}
} else {
SeatOpKind::Move
};
break 'res (op, child);
}
}
} else {
for child in self.children.iter() {
let body = child.body.get();
if seat_data.y < body.y1() {
let op = if seat_data.y < body.y1() - title_height - 1 {
SeatOpKind::Resize {
dist_left: seat_data.y - child.prev().unwrap().body.get().y2(),
dist_right: body.y1() - seat_data.y,
}
} else {
SeatOpKind::Move
};
break 'res (op, child);
}
}
};
}
return;
};
seat_data.op = Some(SeatOp { child, kind })
@ -1049,6 +1092,7 @@ impl Node for ContainerNode {
Some(c) => c,
None => return,
};
node.focus_history.set(None);
let link = node.append(ContainerChild {
node: new.clone(),
active: Cell::new(false),
@ -1056,6 +1100,8 @@ impl Node for ContainerNode {
content: Cell::new(node.content.get()),
factor: Cell::new(node.factor.get()),
title: Default::default(),
title_rect: Cell::new(node.title_rect.get()),
focus_history: Cell::new(None),
});
let body = link.body.get();
drop(node);
@ -1083,6 +1129,7 @@ impl Node for ContainerNode {
}
let node = {
let node = node;
node.focus_history.set(None);
node.to_ref()
};
let num_children = self.num_children.fetch_sub(1) - 1;
@ -1137,6 +1184,7 @@ impl Node for ContainerNode {
None => return,
};
node.active.set(active);
node.focus_history.set(Some(self.focus_history.add_last(node.clone())));
self.schedule_compute_render_data();
}
@ -1242,5 +1290,6 @@ fn direction_to_split(dir: Direction) -> (ContainerSplit, bool) {
Direction::Down => (ContainerSplit::Vertical, false),
Direction::Up => (ContainerSplit::Vertical, true),
Direction::Right => (ContainerSplit::Horizontal, false),
Direction::Unspecified => (ContainerSplit::Horizontal, true),
}
}

View file

@ -4,7 +4,6 @@ use {
cursor::KnownCursor,
ifs::{
wl_seat::{NodeSeatState, WlSeatGlobal},
wl_surface::xwindow::Xwindow,
zwlr_layer_shell_v1::{OVERLAY, TOP},
},
tree::{walker::NodeVisitor, FindTreeResult, FoundNode, Node, NodeId, OutputNode},
@ -17,7 +16,6 @@ pub struct DisplayNode {
pub id: NodeId,
pub outputs: CopyHashMap<ConnectorId, Rc<OutputNode>>,
pub stacked: LinkedList<Rc<dyn Node>>,
pub xstacked: LinkedList<Rc<Xwindow>>,
pub seat_state: NodeSeatState,
}
@ -27,7 +25,6 @@ impl DisplayNode {
id,
outputs: Default::default(),
stacked: Default::default(),
xstacked: Default::default(),
seat_state: Default::default(),
}
}
@ -42,6 +39,10 @@ impl Node for DisplayNode {
&self.seat_state
}
fn visible(&self) -> bool {
true
}
fn destroy_node(&self, _detach: bool) {
let mut outputs = self.outputs.lock();
for output in outputs.values() {
@ -79,7 +80,9 @@ impl Node for DisplayNode {
x,
y,
});
if output.find_layer_surface_at(x, y, &[OVERLAY, TOP], tree) == FindTreeResult::AcceptsInput {
if output.find_layer_surface_at(x, y, &[OVERLAY, TOP], tree)
== FindTreeResult::AcceptsInput
{
return FindTreeResult::AcceptsInput;
}
tree.pop();

View file

@ -327,6 +327,18 @@ impl Node for FloatNode {
&self.seat_state
}
fn visible(&self) -> bool {
self.visible.get()
}
fn set_visible(&self, visible: bool) {
self.visible.set(visible);
if let Some(child) = self.child.get() {
child.set_visible(visible);
}
self.seat_state.set_visible(self, visible);
}
fn destroy_node(&self, _detach: bool) {
let _v = self.display_link.take();
let _v = self.workspace_link.take();

View file

@ -1,4 +1,3 @@
use std::cell::Cell;
use {
crate::{
backend::Mode,
@ -8,6 +7,7 @@ use {
wl_output::WlOutputGlobal,
wl_seat::{NodeSeatState, WlSeatGlobal},
wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
zwlr_layer_shell_v1::{BACKGROUND, BOTTOM},
},
rect::Rect,
render::{Renderer, Texture},
@ -18,13 +18,12 @@ use {
utils::{clonecell::CloneCell, errorfmt::ErrorFmt, linkedlist::LinkedList},
},
std::{
cell::RefCell,
cell::{Cell, RefCell},
fmt::{Debug, Formatter},
ops::{Deref, Sub},
rc::Rc,
},
};
use crate::ifs::zwlr_layer_shell_v1::{BACKGROUND, BOTTOM};
tree_id!(OutputNodeId);
pub struct OutputNode {
@ -119,12 +118,13 @@ impl OutputNode {
}
pub fn show_workspace(&self, ws: &Rc<WorkspaceNode>) {
ws.visible.set(true);
if let Some(old) = self.workspace.set(Some(ws.clone())) {
if old.id != ws.id {
old.visible.set(false);
if old.id == ws.id {
return;
}
old.visible.set(false);
}
ws.visible.set(true);
ws.clone().change_extents(&self.workspace_rect());
}
@ -172,7 +172,13 @@ impl OutputNode {
self.global.send_mode();
}
pub fn find_layer_surface_at(&self, x: i32, y: i32, layers: &[u32], tree: &mut Vec<FoundNode>) -> FindTreeResult {
pub fn find_layer_surface_at(
&self,
x: i32,
y: i32,
layers: &[u32],
tree: &mut Vec<FoundNode>,
) -> FindTreeResult {
let len = tree.len();
for layer in layers.iter().copied() {
for surface in self.layers[layer as usize].rev_iter() {
@ -218,6 +224,10 @@ impl Node for OutputNode {
&self.seat_state
}
fn visible(&self) -> bool {
true
}
fn destroy_node(&self, detach: bool) {
if detach {
self.state.root.clone().remove_child(self);

View file

@ -18,6 +18,7 @@ pub trait ToplevelNode {
fn set_active(&self, active: bool);
fn activate(&self);
fn toggle_floating(self: Rc<Self>);
fn close(&self);
}
#[derive(Default)]

View file

@ -108,6 +108,68 @@ impl<T: NodeVisitorBase> NodeVisitor for T {
}
}
pub struct GenericNodeVisitor<F> {
f: F,
}
pub fn generic_node_visitor<F: FnMut(Rc<dyn Node>)>(f: F) -> GenericNodeVisitor<F> {
GenericNodeVisitor {
f,
}
}
impl<F: FnMut(Rc<dyn Node>)> NodeVisitor for GenericNodeVisitor<F> {
fn visit_surface(&mut self, node: &Rc<WlSurface>) {
(self.f)(node.clone());
node.visit_children(self);
}
fn visit_container(&mut self, node: &Rc<ContainerNode>) {
(self.f)(node.clone());
node.visit_children(self);
}
fn visit_toplevel(&mut self, node: &Rc<XdgToplevel>) {
(self.f)(node.clone());
node.visit_children(self);
}
fn visit_popup(&mut self, node: &Rc<XdgPopup>) {
(self.f)(node.clone());
node.visit_children(self);
}
fn visit_display(&mut self, node: &Rc<DisplayNode>) {
(self.f)(node.clone());
node.visit_children(self);
}
fn visit_output(&mut self, node: &Rc<OutputNode>) {
(self.f)(node.clone());
node.visit_children(self);
}
fn visit_float(&mut self, node: &Rc<FloatNode>) {
(self.f)(node.clone());
node.visit_children(self);
}
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
(self.f)(node.clone());
node.visit_children(self);
}
fn visit_layer_surface(&mut self, node: &Rc<ZwlrLayerSurfaceV1>) {
(self.f)(node.clone());
node.visit_children(self);
}
fn visit_xwindow(&mut self, node: &Rc<Xwindow>) {
(self.f)(node.clone());
node.visit_children(self);
}
}
// pub fn visit_containers<F: FnMut(&Rc<ContainerNode>)>(f: F) -> impl NodeVisitor {
// struct V<F>(F);
// impl<F: FnMut(&Rc<ContainerNode>)> NodeVisitorBase for V<F> {

View file

@ -48,6 +48,18 @@ impl Node for WorkspaceNode {
&self.seat_state
}
fn visible(&self) -> bool {
self.visible.get()
}
fn set_visible(&self, visible: bool) {
self.visible.set(visible);
if let Some(container) = self.container.get() {
container.set_visible(visible);
}
self.seat_state.set_visible(self, visible);
}
fn destroy_node(&self, detach: bool) {
if detach {
self.output.get().remove_child(self);

View file

@ -9,6 +9,8 @@ use {
},
};
const LINKED_NODE_REF_COUNT: usize = !(!0 >> 1);
pub struct LinkedList<T> {
root: LinkedNode<T>,
}
@ -28,7 +30,7 @@ impl<T> Default for LinkedList<T> {
impl<T> LinkedList<T> {
pub fn new() -> Self {
let node = Box::into_raw(Box::new(NodeData {
rc: NumCell::new(1),
rc: NumCell::new(LINKED_NODE_REF_COUNT),
prev: Cell::new(NonNull::dangling()),
next: Cell::new(NonNull::dangling()),
data: None,
@ -226,6 +228,14 @@ impl<T> NodeRef<T> {
unsafe { append(self.data, t) }
}
pub fn prepend_existing(&self, t: &NodeRef<T>) {
unsafe { prepend_existing(self.data, t) }
}
pub fn append_existing(&self, t: &NodeRef<T>) {
unsafe { append_existing(self.data, t) }
}
fn peer<F>(&self, peer: F) -> Option<NodeRef<T>>
where
F: FnOnce(&NodeData<T>) -> &Cell<NonNull<NodeData<T>>>,
@ -249,6 +259,14 @@ impl<T> NodeRef<T> {
pub fn next(&self) -> Option<NodeRef<T>> {
self.peer(|d| &d.next)
}
unsafe fn detach(&self) {
let data = self.data.as_ref();
data.prev.get().as_ref().next.set(data.next.get());
data.next.get().as_ref().prev.set(data.prev.get());
data.prev.set(self.data);
data.next.set(self.data);
}
}
struct NodeData<T> {
@ -267,27 +285,13 @@ unsafe fn dec_ref_count<T>(slf: NonNull<NodeData<T>>, n: usize) {
impl<T> Drop for LinkedNode<T> {
fn drop(&mut self) {
unsafe {
{
let data = self.data.as_ref();
data.prev.get().as_ref().next.set(data.next.get());
data.next.get().as_ref().prev.set(data.prev.get());
data.prev.set(self.data);
data.next.set(self.data);
}
dec_ref_count(self.data, 1);
self.detach();
dec_ref_count(self.data, LINKED_NODE_REF_COUNT);
}
}
}
impl<T> LinkedNode<T> {
pub fn prepend(&self, t: T) -> LinkedNode<T> {
unsafe { prepend(self.data, t) }
}
pub fn append(&self, t: T) -> LinkedNode<T> {
unsafe { append(self.data, t) }
}
pub fn to_ref(&self) -> NodeRef<T> {
unsafe {
self.data.as_ref().rc.fetch_add(1);
@ -296,10 +300,24 @@ impl<T> LinkedNode<T> {
}
}
unsafe fn prepend_existing<T>(data: NonNull<NodeData<T>>, t: &NodeRef<T>) {
let dref = data.as_ref();
let tref = t.data.as_ref();
if tref.rc.get() < LINKED_NODE_REF_COUNT {
log::error!("Trying to prepend a node whose linked node has already been dropped");
return;
}
t.detach();
tref.prev.set(dref.prev.get());
tref.next.set(data);
dref.prev.get().as_ref().next.set(t.data);
dref.prev.set(t.data);
}
unsafe fn prepend<T>(data: NonNull<NodeData<T>>, t: T) -> LinkedNode<T> {
let dref = data.as_ref();
let node = NonNull::new_unchecked(Box::into_raw(Box::new(NodeData {
rc: NumCell::new(1),
rc: NumCell::new(LINKED_NODE_REF_COUNT),
prev: Cell::new(dref.prev.get()),
next: Cell::new(data),
data: Some(t),
@ -309,10 +327,24 @@ unsafe fn prepend<T>(data: NonNull<NodeData<T>>, t: T) -> LinkedNode<T> {
LinkedNode { data: node }
}
unsafe fn append_existing<T>(data: NonNull<NodeData<T>>, t: &NodeRef<T>) {
let dref = data.as_ref();
let tref = t.data.as_ref();
if tref.rc.get() < LINKED_NODE_REF_COUNT {
log::error!("Trying to append a node whose linked node has already been dropped");
return;
}
t.detach();
tref.prev.set(data);
tref.next.set(dref.next.get());
dref.next.get().as_ref().prev.set(t.data);
dref.next.set(t.data);
}
unsafe fn append<T>(data: NonNull<NodeData<T>>, t: T) -> LinkedNode<T> {
let dref = data.as_ref();
let node = NonNull::new_unchecked(Box::into_raw(Box::new(NodeData {
rc: NumCell::new(1),
rc: NumCell::new(LINKED_NODE_REF_COUNT),
prev: Cell::new(data),
next: Cell::new(dref.next.get()),
data: Some(t),

View file

@ -2,6 +2,7 @@ mod sys;
use {
crate::{
utils::oserror::OsError,
video::drm::sys::{
create_lease, drm_event, drm_event_vblank, gem_close, get_cap,
get_device_name_from_fd2, get_minor_name_from_fd, get_node_type_from_fd, get_nodes,
@ -13,7 +14,6 @@ use {
DRM_MODE_OBJECT_CRTC, DRM_MODE_OBJECT_ENCODER, DRM_MODE_OBJECT_FB,
DRM_MODE_OBJECT_MODE, DRM_MODE_OBJECT_PLANE, DRM_MODE_OBJECT_PROPERTY,
},
utils::oserror::OsError,
},
ahash::AHashMap,
bstr::{BString, ByteSlice},
@ -31,8 +31,8 @@ use {
use crate::{
backend,
video::{dma::DmaBuf, INVALID_MODIFIER},
utils::{errorfmt::ErrorFmt, stack::Stack, syncqueue::SyncQueue, vec_ext::VecExt},
video::{dma::DmaBuf, INVALID_MODIFIER},
};
pub use sys::{
drm_mode_modeinfo, DRM_CLIENT_CAP_ATOMIC, DRM_MODE_ATOMIC_ALLOW_MODESET,

View file

@ -3,13 +3,13 @@
use {
crate::{
utils::{bitflags::BitflagsExt, oserror::OsError, trim::AsciiTrim},
video::drm::{
DrmBlob, DrmCardResources, DrmConnector, DrmConnectorInfo, DrmCrtc, DrmEncoder,
DrmEncoderInfo, DrmError, DrmFb, DrmModeInfo, DrmPlane, DrmPlaneInfo, DrmProperty,
DrmPropertyDefinition, DrmPropertyEnumValue, DrmPropertyType, DrmPropertyValue,
NodeType,
},
utils::{bitflags::BitflagsExt, oserror::OsError, trim::AsciiTrim},
},
ahash::AHashMap,
bstr::ByteSlice,

View file

@ -1,11 +1,11 @@
use {
crate::{
format::formats,
video::{
dma::{DmaBuf, DmaBufPlane},
drm::{Drm, DrmError},
ModifiedFormat, INVALID_MODIFIER,
},
format::formats,
},
std::{
fmt::{Debug, Formatter},

View file

@ -271,4 +271,5 @@ pub enum XWaylandEvent {
SurfaceDestroyed(WlSurfaceId),
Configure(Rc<Xwindow>),
Activate(Rc<XwindowData>),
Close(Rc<XwindowData>),
}

View file

@ -55,6 +55,7 @@ atoms! {
CLIPBOARD,
CLIPBOARD_MANAGER,
COMPOUND_TEXT,
DELETE,
INCR,
_MOTIF_WM_HINTS,
@ -370,6 +371,7 @@ impl Wm {
XWaylandEvent::Configure(event) => self.handle_xwayland_configure(event).await,
XWaylandEvent::SurfaceDestroyed(event) => self.handle_xwayland_surface_destroyed(event),
XWaylandEvent::Activate(window) => self.activate_window(Some(&window)).await,
XWaylandEvent::Close(window) => self.close_window(&window).await,
}
}
@ -534,7 +536,7 @@ impl Wm {
Ok(ty) if ty == ATOM_STRING => {}
Ok(ty) if ty == self.atoms.UTF8_STRING => {}
Ok(ty) => {
log::error!("WM_WINDOW_ROLE property has unexpected type {}", ty);
self.unexpected_type(data.window_id, "WM_WINDOW_ROLE", ty).await;
return;
}
Err(XconError::PropertyUnavailable) => {
@ -563,7 +565,7 @@ impl Wm {
Ok(ty) if ty == ATOM_STRING => {}
Ok(ty) if ty == self.atoms.UTF8_STRING => {}
Ok(ty) => {
log::error!("WM_CLASS property has unexpected type {}", ty);
self.unexpected_type(data.window_id, "WM_CLASS", ty).await;
return;
}
Err(XconError::PropertyUnavailable) => {
@ -590,11 +592,12 @@ impl Wm {
{
Ok(ty) if ty == ATOM_STRING && data.info.utf8_title.get() => return,
Ok(ty) if ty == ATOM_STRING => {}
Ok(ty) if ty == self.atoms.COMPOUND_TEXT => {} // used by java. assume utf-8.
Ok(ty) if ty == self.atoms.UTF8_STRING => {
data.info.utf8_title.set(true);
}
Ok(ty) => {
log::error!("{} property has unexpected type {}", name, ty);
self.unexpected_type(data.window_id, name, ty).await;
return;
}
Err(XconError::PropertyUnavailable) => return,
@ -607,6 +610,15 @@ impl Wm {
data.title_changed();
}
async fn unexpected_type(&self, window: u32, prop: &str, ty: u32) {
let mut ty_name = "unknown".as_bytes().as_bstr();
let res = self.c.call(&GetAtomName { atom: ty }).await;
if let Ok(res) = &res {
ty_name = res.get().name;
}
log::error!("Property {} of window {} has unexpected type {} ({})", prop, window, ty_name, ty);
}
async fn load_window_wm_name(&self, data: &Rc<XwindowData>) {
self.load_window_wm_name2(data, ATOM_WM_NAME, "WM_NAME")
.await;
@ -786,7 +798,7 @@ impl Wm {
Ok(ty) if ty == ATOM_STRING => {}
Ok(ty) if ty == self.atoms.UTF8_STRING => {}
Ok(ty) => {
log::error!("_NET_STARTUP_ID property has unexpected type {}", ty);
self.unexpected_type(data.window_id, "_NET_STARTUP_ID", ty).await;
return;
}
Err(XconError::PropertyUnavailable) => return,