autocommit 2022-04-08 23:02:38 CEST
This commit is contained in:
parent
0bd9a70e69
commit
21e2216ce5
40 changed files with 587 additions and 255 deletions
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,6 +146,9 @@ pub enum ClientMessage<'a> {
|
|||
seat: Seat,
|
||||
axis: Axis,
|
||||
},
|
||||
Close {
|
||||
seat: Seat,
|
||||
},
|
||||
FocusParent {
|
||||
seat: Seat,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ pub enum LogLevel {
|
|||
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Direction {
|
||||
Unspecified,
|
||||
Left,
|
||||
Down,
|
||||
Up,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use {
|
||||
crate::{video::drm::ConnectorType, fixed::Fixed},
|
||||
crate::{fixed::Fixed, video::drm::ConnectorType},
|
||||
std::{
|
||||
fmt::{Debug, Display, Formatter},
|
||||
rc::Rc,
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
35
src/edid.rs
35
src/edid.rs
|
|
@ -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}",
|
||||
];
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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::{
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
|||
11
src/tree.rs
11
src/tree.rs
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use {
|
||||
crate::{
|
||||
format::formats,
|
||||
video::{
|
||||
dma::{DmaBuf, DmaBufPlane},
|
||||
drm::{Drm, DrmError},
|
||||
ModifiedFormat, INVALID_MODIFIER,
|
||||
},
|
||||
format::formats,
|
||||
},
|
||||
std::{
|
||||
fmt::{Debug, Formatter},
|
||||
|
|
|
|||
|
|
@ -271,4 +271,5 @@ pub enum XWaylandEvent {
|
|||
SurfaceDestroyed(WlSurfaceId),
|
||||
Configure(Rc<Xwindow>),
|
||||
Activate(Rc<XwindowData>),
|
||||
Close(Rc<XwindowData>),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue