1
0
Fork 0
forked from wry/wry

autocommit 2022-04-04 00:28:58 CEST

This commit is contained in:
Julian Orth 2022-04-04 00:28:58 +02:00
parent 9ec1c5c995
commit 1f71290dab
21 changed files with 1217 additions and 132 deletions

View file

@ -9,14 +9,25 @@ pub trait Backend {
fn switch_to(&self, vtnr: u32); fn switch_to(&self, vtnr: u32);
} }
pub trait Output { #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct Mode {
pub width: i32,
pub height: i32,
pub refresh_rate: u32,
}
pub trait Connector {
fn id(&self) -> OutputId; fn id(&self) -> OutputId;
fn removed(&self) -> bool; fn event(&self) -> Option<ConnectorEvent>;
fn width(&self) -> i32;
fn height(&self) -> i32;
fn on_change(&self, cb: Rc<dyn Fn()>); fn on_change(&self, cb: Rc<dyn Fn()>);
} }
#[derive(Debug)]
pub enum ConnectorEvent {
Removed,
ModeChanged(Mode),
}
pub trait InputDevice { pub trait InputDevice {
fn id(&self) -> InputDeviceId; fn id(&self) -> InputDeviceId;
fn removed(&self) -> bool; fn removed(&self) -> bool;
@ -49,7 +60,7 @@ pub enum InputDeviceAccelProfile {
} }
pub enum BackendEvent { pub enum BackendEvent {
NewOutput(Rc<dyn Output>), NewConnector(Rc<dyn Connector>),
NewInputDevice(Rc<dyn InputDevice>), NewInputDevice(Rc<dyn InputDevice>),
} }

View file

@ -1,4 +1,4 @@
use crate::backend::{Backend, Output, OutputId}; use crate::backend::{Backend, Connector, ConnectorEvent, OutputId};
use std::rc::Rc; use std::rc::Rc;
pub struct DummyBackend {} pub struct DummyBackend {}
@ -13,21 +13,13 @@ pub struct DummyOutput {
pub id: OutputId, pub id: OutputId,
} }
impl Output for DummyOutput { impl Connector for DummyOutput {
fn id(&self) -> OutputId { fn id(&self) -> OutputId {
self.id self.id
} }
fn removed(&self) -> bool { fn event(&self) -> Option<ConnectorEvent> {
false None
}
fn width(&self) -> i32 {
100
}
fn height(&self) -> i32 {
100
} }
fn on_change(&self, _cb: Rc<dyn Fn()>) { fn on_change(&self, _cb: Rc<dyn Fn()>) {

View file

@ -232,6 +232,7 @@ impl MetalBackend {
} }
fn handle_drm_change(self: &Rc<Self>, _dev: UdevDevice) -> Option<()> { fn handle_drm_change(self: &Rc<Self>, _dev: UdevDevice) -> Option<()> {
// TODO: Handle monitor connections and connector hotplug
None None
} }

View file

@ -1,5 +1,5 @@
use crate::async_engine::{AsyncFd, SpawnedFuture}; use crate::async_engine::{AsyncFd, SpawnedFuture};
use crate::backend::{BackendEvent, Output, OutputId}; use crate::backend::{BackendEvent, Connector, ConnectorEvent, Mode, OutputId};
use crate::backends::metal::{DrmId, MetalBackend, MetalError}; use crate::backends::metal::{DrmId, MetalBackend, MetalError};
use crate::drm::drm::{ use crate::drm::drm::{
drm_mode_modeinfo, Change, ConnectorStatus, ConnectorType, DrmBlob, DrmConnector, DrmCrtc, drm_mode_modeinfo, Change, ConnectorStatus, ConnectorType, DrmBlob, DrmConnector, DrmCrtc,
@ -24,6 +24,7 @@ use std::ffi::CString;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::rc::Rc; use std::rc::Rc;
use uapi::c; use uapi::c;
use crate::utils::syncqueue::SyncQueue;
pub struct PendingDrmDevice { pub struct PendingDrmDevice {
pub id: DrmId, pub id: DrmId,
@ -77,6 +78,8 @@ pub struct MetalConnector {
pub modes: Vec<DrmModeInfo>, pub modes: Vec<DrmModeInfo>,
pub mode: CloneCell<Option<Rc<DrmModeInfo>>>, pub mode: CloneCell<Option<Rc<DrmModeInfo>>>,
pub events: SyncQueue<ConnectorEvent>,
pub buffers: CloneCell<Option<Rc<[RenderBuffer; 2]>>>, pub buffers: CloneCell<Option<Rc<[RenderBuffer; 2]>>>,
pub next_buffer: NumCell<usize>, pub next_buffer: NumCell<usize>,
@ -110,27 +113,13 @@ impl Debug for OnChange {
} }
} }
impl Output for MetalConnector { impl Connector for MetalConnector {
fn id(&self) -> OutputId { fn id(&self) -> OutputId {
self.output_id self.output_id
} }
fn removed(&self) -> bool { fn event(&self) -> Option<ConnectorEvent> {
false self.events.pop()
}
fn width(&self) -> i32 {
match self.mode.get() {
Some(m) => m.hdisplay as _,
_ => 0,
}
}
fn height(&self) -> i32 {
match self.mode.get() {
Some(m) => m.vdisplay as _,
_ => 0,
}
} }
fn on_change(&self, cb: Rc<dyn Fn()>) { fn on_change(&self, cb: Rc<dyn Fn()>) {
@ -223,12 +212,22 @@ fn create_connector(
} }
} }
let props = collect_properties(&dev.master, connector)?; let props = collect_properties(&dev.master, connector)?;
let mode = info.modes.first().cloned().map(Rc::new);
let events = SyncQueue::default();
if let Some(mode) = &mode {
events.push(ConnectorEvent::ModeChanged(Mode {
width: mode.hdisplay as _,
height: mode.vdisplay as _,
refresh_rate: mode.refresh_rate(),
}));
}
Ok(MetalConnector { Ok(MetalConnector {
id: connector, id: connector,
master: dev.master.clone(), master: dev.master.clone(),
output_id: state.output_ids.next(), output_id: state.output_ids.next(),
crtcs, crtcs,
mode: CloneCell::new(info.modes.first().cloned().map(Rc::new)), mode: CloneCell::new(mode),
events,
modes: info.modes, modes: info.modes,
buffers: Default::default(), buffers: Default::default(),
next_buffer: Default::default(), next_buffer: Default::default(),
@ -486,6 +485,9 @@ impl MetalBackend {
self.init_drm_device(&slf)?; self.init_drm_device(&slf)?;
for connector in slf.connectors.values() { for connector in slf.connectors.values() {
self.state
.backend_events
.push(BackendEvent::NewConnector(connector.clone()));
if connector.primary_plane.get().is_some() { if connector.primary_plane.get().is_some() {
self.start_connector(connector); self.start_connector(connector);
} }
@ -880,9 +882,6 @@ impl MetalBackend {
fn start_connector(&self, connector: &Rc<MetalConnector>) { fn start_connector(&self, connector: &Rc<MetalConnector>) {
let mode = connector.mode.get().unwrap(); let mode = connector.mode.get().unwrap();
self.state
.backend_events
.push(BackendEvent::NewOutput(connector.clone()));
log::info!( log::info!(
"Initialized connector {}-{} with mode {:?}", "Initialized connector {}-{} with mode {:?}",
connector.connector_type, connector.connector_type,
@ -905,7 +904,7 @@ impl MetalBackend {
if let Some(node) = self.state.root.outputs.get(&connector.output_id) { if let Some(node) = self.state.root.outputs.get(&connector.output_id) {
buffer buffer
.egl .egl
.render(&*node, &self.state, Some(node.position.get())); .render(&*node, &self.state, Some(node.global.pos.get()));
} }
let mut changes = connector.master.change(); let mut changes = connector.master.change();
changes.change_object(plane.id, |c| { changes.change_object(plane.id, |c| {

View file

@ -1,8 +1,5 @@
use crate::async_engine::{Phase, SpawnedFuture}; use crate::async_engine::{Phase, SpawnedFuture};
use crate::backend::{ use crate::backend::{Backend, BackendEvent, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent, KeyState, Connector, OutputId, ScrollAxis, Mode, ConnectorEvent};
Backend, BackendEvent, InputDevice, InputDeviceAccelProfile, InputDeviceCapability,
InputDeviceId, InputEvent, KeyState, Output, OutputId, ScrollAxis,
};
use crate::drm::drm::{Drm, DrmError}; use crate::drm::drm::{Drm, DrmError};
use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING}; use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
use crate::drm::{ModifiedFormat, INVALID_MODIFIER}; use crate::drm::{ModifiedFormat, INVALID_MODIFIER};
@ -42,6 +39,7 @@ use std::cell::{Cell, RefCell};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use crate::utils::syncqueue::SyncQueue;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum XBackendError { pub enum XBackendError {
@ -396,7 +394,7 @@ impl XBackendData {
id: self.state.output_ids.next(), id: self.state.output_ids.next(),
_backend: self.clone(), _backend: self.clone(),
window: window_id, window: window_id,
removed: Cell::new(false), events: Default::default(),
width: Cell::new(0), width: Cell::new(0),
height: Cell::new(0), height: Cell::new(0),
serial: Default::default(), serial: Default::default(),
@ -479,7 +477,7 @@ impl XBackendData {
self.outputs.set(window_id, output.clone()); self.outputs.set(window_id, output.clone());
self.state self.state
.backend_events .backend_events
.push(BackendEvent::NewOutput(output.clone())); .push(BackendEvent::NewConnector(output.clone()));
self.present(&output).await; self.present(&output).await;
Ok(()) Ok(())
} }
@ -636,10 +634,6 @@ impl XBackendData {
} }
async fn present(&self, output: &Rc<XOutput>) { async fn present(&self, output: &Rc<XOutput>) {
if output.removed.get() {
return;
}
let serial = output.serial.fetch_add(1); let serial = output.serial.fetch_add(1);
let image = &output.images[output.next_image.fetch_add(1) % output.images.len()]; let image = &output.images[output.next_image.fetch_add(1) % output.images.len()];
@ -648,7 +642,7 @@ impl XBackendData {
if let Some(node) = self.state.root.outputs.get(&output.id) { if let Some(node) = self.state.root.outputs.get(&output.id) {
let fb = image.fb.get(); let fb = image.fb.get();
fb.render(&*node, &self.state, Some(node.position.get())); fb.render(&*node, &self.state, Some(node.global.pos.get()));
} }
let pp = PresentPixmap { let pp = PresentPixmap {
@ -795,7 +789,7 @@ impl XBackendData {
Some(o) => o, Some(o) => o,
_ => return Ok(()), _ => return Ok(()),
}; };
output.removed.set(true); output.events.push(ConnectorEvent::Removed);
output.changed(); output.changed();
Ok(()) Ok(())
} }
@ -820,6 +814,11 @@ impl XBackendData {
old.fb.set(new.fb.get()); old.fb.set(new.fb.get());
old.pixmap.set(new.pixmap.get()); old.pixmap.set(new.pixmap.get());
} }
output.events.push(ConnectorEvent::ModeChanged(Mode {
width,
height,
refresh_rate: 60, // TODO
}));
output.changed(); output.changed();
} }
Ok(()) Ok(())
@ -830,7 +829,7 @@ struct XOutput {
id: OutputId, id: OutputId,
_backend: Rc<XBackendData>, _backend: Rc<XBackendData>,
window: u32, window: u32,
removed: Cell<bool>, events: SyncQueue<ConnectorEvent>,
width: Cell<i32>, width: Cell<i32>,
height: Cell<i32>, height: Cell<i32>,
serial: NumCell<u32>, serial: NumCell<u32>,
@ -856,21 +855,13 @@ impl XOutput {
} }
} }
impl Output for XOutput { impl Connector for XOutput {
fn id(&self) -> OutputId { fn id(&self) -> OutputId {
self.id self.id
} }
fn removed(&self) -> bool { fn event(&self) -> Option<ConnectorEvent> {
self.removed.get() self.events.pop()
}
fn width(&self) -> i32 {
self.width.get()
}
fn height(&self) -> i32 {
self.height.get()
} }
fn on_change(&self, cb: Rc<dyn Fn()>) { fn on_change(&self, cb: Rc<dyn Fn()>) {

View file

@ -120,12 +120,12 @@ fn main_(logger: Arc<Logger>, _args: &RunArgs) -> Result<(), MainError> {
{ {
let dummy_output = Rc::new(OutputNode { let dummy_output = Rc::new(OutputNode {
id: state.node_ids.next(), id: state.node_ids.next(),
position: Default::default(),
global: Rc::new(WlOutputGlobal::new( global: Rc::new(WlOutputGlobal::new(
state.globals.name(), state.globals.name(),
Rc::new(DummyOutput { Rc::new(DummyOutput {
id: state.output_ids.next(), id: state.output_ids.next(),
}), }),
0,
)), )),
workspaces: Default::default(), workspaces: Default::default(),
workspace: Default::default(), workspace: Default::default(),

View file

@ -32,6 +32,7 @@ pub use sys::{
drm_mode_modeinfo, DRM_CLIENT_CAP_ATOMIC, DRM_MODE_ATOMIC_ALLOW_MODESET, drm_mode_modeinfo, DRM_CLIENT_CAP_ATOMIC, DRM_MODE_ATOMIC_ALLOW_MODESET,
DRM_MODE_ATOMIC_NONBLOCK, DRM_MODE_PAGE_FLIP_EVENT, DRM_MODE_ATOMIC_NONBLOCK, DRM_MODE_PAGE_FLIP_EVENT,
}; };
use crate::utils::vec_ext::VecExt;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum DrmError { pub enum DrmError {
@ -63,6 +64,8 @@ pub enum DrmError {
GetPropBlob(#[source] OsError), GetPropBlob(#[source] OsError),
#[error("Property has an invalid size")] #[error("Property has an invalid size")]
InvalidProbSize, InvalidProbSize,
#[error("Property has a size that is not a multiple of the vector type")]
UnalignedPropSize,
#[error("Could not perform drm properties ioctl")] #[error("Could not perform drm properties ioctl")]
GetProperties(#[source] OsError), GetProperties(#[source] OsError),
#[error("Could not perform drm atomic ioctl")] #[error("Could not perform drm atomic ioctl")]
@ -316,6 +319,25 @@ impl DrmMaster {
} }
} }
pub fn getblob_vec<T: Pod>(&self, blob: DrmBlob) -> Result<Vec<T>, DrmError> {
assert_ne!(mem::size_of::<T>(), 0);
let mut vec = vec![];
loop {
let (_, bytes) = vec.split_at_spare_mut_bytes_ext();
match mode_getprobblob(self.raw(), blob.0, bytes) {
Err(e) => return Err(DrmError::GetPropBlob(e)),
Ok(n) if n % mem::size_of::<T>() != 0 => return Err(DrmError::UnalignedPropSize),
Ok(n) if n <= bytes.len() => {
unsafe {
vec.set_len(n / mem::size_of::<T>());
}
return Ok(vec);
}
Ok(n) => vec.reserve_exact(n / mem::size_of::<T>()),
}
}
}
pub fn event(&self) -> Result<Option<DrmEvent>, DrmError> { pub fn event(&self) -> Result<Option<DrmEvent>, DrmError> {
if self.events.is_empty() { if self.events.is_empty() {
let mut buf = self.buf.borrow_mut(); let mut buf = self.buf.borrow_mut();
@ -570,6 +592,16 @@ impl DrmModeInfo {
name, name,
} }
} }
pub fn refresh_rate(&self) -> u32 {
let clock_mhz = self.clock as u64 * 1_000_000;
let htotal = self.htotal as u64;
let vtotal = self.vtotal as u64;
(((clock_mhz / htotal) + (vtotal / 2)) / vtotal) as u32
// simplifies to
// clock_mhz / (htotal * vtotal) + 1/2
// why round up (+1/2) instead of down?
}
} }
#[derive(Debug)] #[derive(Debug)]

1059
src/edid.rs Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
use crate::backend::Output; use crate::backend::Connector;
use crate::client::{Client, ClientError, ClientId}; use crate::client::{Client, ClientError, ClientId};
use crate::globals::{Global, GlobalName}; use crate::globals::{Global, GlobalName};
use crate::ifs::zxdg_output_v1::ZxdgOutputV1; use crate::ifs::zxdg_output_v1::ZxdgOutputV1;
@ -17,6 +17,7 @@ use std::cell::{Cell, RefCell};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use crate::backend;
const SP_UNKNOWN: i32 = 0; const SP_UNKNOWN: i32 = 0;
#[allow(dead_code)] #[allow(dead_code)]
@ -52,18 +53,20 @@ const MODE_PREFERRED: u32 = 2;
pub struct WlOutputGlobal { pub struct WlOutputGlobal {
name: GlobalName, name: GlobalName,
output: Rc<dyn Output>, pub connector: Rc<dyn Connector>,
pos: Cell<Rect>, pub pos: Cell<Rect>,
pub mode: Cell<backend::Mode>,
pub node: CloneCell<Option<Rc<OutputNode>>>, pub node: CloneCell<Option<Rc<OutputNode>>>,
pub bindings: RefCell<AHashMap<ClientId, AHashMap<WlOutputId, Rc<WlOutput>>>>, pub bindings: RefCell<AHashMap<ClientId, AHashMap<WlOutputId, Rc<WlOutput>>>>,
} }
impl WlOutputGlobal { impl WlOutputGlobal {
pub fn new(name: GlobalName, output: Rc<dyn Output>) -> Self { pub fn new(name: GlobalName, connector: Rc<dyn Connector>, x1: i32) -> Self {
Self { Self {
name, name,
output: output.clone(), connector: connector.clone(),
pos: Cell::new(Rect::new_sized(0, 0, output.width(), output.height()).unwrap()), pos: Cell::new(Rect::new_empty(x1, 0)),
mode: Default::default(),
node: Default::default(), node: Default::default(),
bindings: Default::default(), bindings: Default::default(),
} }
@ -73,30 +76,18 @@ impl WlOutputGlobal {
self.pos.get() self.pos.get()
} }
pub fn update_properties(&self) { pub fn send_mode(&self) {
let width = self.output.width(); let bindings = self.bindings.borrow_mut();
let height = self.output.height(); for binding in bindings.values() {
for binding in binding.values() {
let pos = self.pos.get(); binding.send_geometry();
let old_width = pos.width(); binding.send_mode();
let old_height = pos.height(); binding.send_scale();
let changed = old_width != width || old_height != height; binding.send_done();
binding.client.flush();
if changed { let xdg = binding.xdg_outputs.lock();
self.pos for xdg in xdg.values() {
.set(Rect::new_sized(pos.x1(), pos.y1(), width, height).unwrap()); xdg.send_updates();
let bindings = self.bindings.borrow_mut();
for binding in bindings.values() {
for binding in binding.values() {
binding.send_geometry();
binding.send_mode();
binding.send_scale();
binding.send_done();
binding.client.flush();
let xdg = binding.xdg_outputs.lock();
for xdg in xdg.values() {
xdg.send_updates();
}
} }
} }
} }

View file

@ -102,7 +102,7 @@ impl XdgPopup {
let mut rel_pos = positioner.get_position(false, false); let mut rel_pos = positioner.get_position(false, false);
let mut abs_pos = rel_pos.move_(parent_abs.x1(), parent_abs.y1()); let mut abs_pos = rel_pos.move_(parent_abs.x1(), parent_abs.y1());
if let Some(ws) = parent.workspace.get() { if let Some(ws) = parent.workspace.get() {
let output_pos = ws.output.get().position.get(); let output_pos = ws.output.get().global.pos.get();
let mut overflow = output_pos.get_overflow(&abs_pos); let mut overflow = output_pos.get_overflow(&abs_pos);
if !overflow.is_contained() { if !overflow.is_contained() {
let mut flip_x = positioner.ca.contains(CA::FLIP_X) && overflow.x_overflow(); let mut flip_x = positioner.ca.contains(CA::FLIP_X) && overflow.x_overflow();

View file

@ -262,7 +262,7 @@ impl ZwlrLayerSurfaceV1 {
if anchor == 0 { if anchor == 0 {
anchor = LEFT | RIGHT | TOP | BOTTOM; anchor = LEFT | RIGHT | TOP | BOTTOM;
} }
let opos = self.output.position.get(); let opos = self.output.global.pos.get();
let mut x1 = opos.x1(); let mut x1 = opos.x1();
let mut y1 = opos.y1(); let mut y1 = opos.y1();
if anchor.contains(LEFT) { if anchor.contains(LEFT) {

View file

@ -82,7 +82,7 @@ impl ZwlrLayerShellV1 {
} }
} }
}; };
log::info!("output = {:?}", output.position.get()); log::info!("output = {:?}", output.global.pos.get());
if req.layer > OVERLAY { if req.layer > OVERLAY {
return Err(GetLayerSurfaceError::UnknownLayer(req.layer)); return Err(GetLayerSurfaceError::UnknownLayer(req.layer));
} }

View file

@ -78,6 +78,7 @@ mod wire_xcon;
mod xcon; mod xcon;
mod xkbcommon; mod xkbcommon;
mod xwayland; mod xwayland;
mod edid;
fn main() { fn main() {
cli::main(); cli::main();

View file

@ -29,7 +29,7 @@ pub struct Renderer<'a> {
impl Renderer<'_> { impl Renderer<'_> {
pub fn render_output(&mut self, output: &OutputNode, x: i32, y: i32) { pub fn render_output(&mut self, output: &OutputNode, x: i32, y: i32) {
let opos = output.position.get(); let opos = output.global.pos.get();
macro_rules! render_layer { macro_rules! render_layer {
($layer:expr) => { ($layer:expr) => {
for ls in $layer.iter() { for ls in $layer.iter() {

View file

@ -184,7 +184,7 @@ impl State {
width += 2 * self.theme.border_width.get(); width += 2 * self.theme.border_width.get();
height += 2 * self.theme.border_width.get() + self.theme.title_height.get(); height += 2 * self.theme.border_width.get() + self.theme.title_height.get();
let output = workspace.output.get(); let output = workspace.output.get();
let output_rect = output.position.get(); let output_rect = output.global.pos.get();
let position = { let position = {
let mut x1 = output_rect.x1(); let mut x1 = output_rect.x1();
let mut y1 = output_rect.y1(); let mut y1 = output_rect.y1();

View file

@ -1,4 +1,4 @@
use crate::backend::{BackendEvent, Output}; use crate::backend::{BackendEvent, Connector};
use crate::state::State; use crate::state::State;
use crate::tasks::input_device; use crate::tasks::input_device;
use crate::tasks::output::OutputHandler; use crate::tasks::output::OutputHandler;
@ -18,12 +18,12 @@ impl BackendEventHandler {
fn handle_event(&mut self, event: BackendEvent) { fn handle_event(&mut self, event: BackendEvent) {
match event { match event {
BackendEvent::NewOutput(output) => self.handle_new_output(output), BackendEvent::NewConnector(output) => self.handle_new_output(output),
BackendEvent::NewInputDevice(s) => input_device::handle(&self.state, s), BackendEvent::NewInputDevice(s) => input_device::handle(&self.state, s),
} }
} }
fn handle_new_output(&mut self, output: Rc<dyn Output>) { fn handle_new_output(&mut self, output: Rc<dyn Connector>) {
let id = output.id(); let id = output.id();
let oh = OutputHandler { let oh = OutputHandler {
state: self.state.clone(), state: self.state.clone(),

View file

@ -1,16 +1,16 @@
use crate::backend::Output; use crate::backend::{Connector, ConnectorEvent};
use crate::ifs::wl_output::WlOutputGlobal; use crate::ifs::wl_output::WlOutputGlobal;
use crate::rect::Rect; use crate::rect::Rect;
use crate::state::State; use crate::state::State;
use crate::tree::{OutputNode, OutputRenderData, WorkspaceNode}; use crate::tree::{OutputNode, OutputRenderData, WorkspaceNode};
use crate::utils::asyncevent::AsyncEvent; use crate::utils::asyncevent::AsyncEvent;
use crate::utils::clonecell::CloneCell; use crate::utils::clonecell::CloneCell;
use std::cell::{Cell, RefCell}; use std::cell::{RefCell};
use std::rc::Rc; use std::rc::Rc;
pub struct OutputHandler { pub struct OutputHandler {
pub state: Rc<State>, pub state: Rc<State>,
pub output: Rc<dyn Output>, pub output: Rc<dyn Connector>,
} }
impl OutputHandler { impl OutputHandler {
@ -21,12 +21,11 @@ impl OutputHandler {
self.output.on_change(Rc::new(move || ae.trigger())); self.output.on_change(Rc::new(move || ae.trigger()));
} }
let name = self.state.globals.name(); let name = self.state.globals.name();
let global = Rc::new(WlOutputGlobal::new(name, self.output.clone())); let x1 = self.state.root.outputs.lock().values().map(|o| o.global.pos.get().x2()).max().unwrap_or(0);
let x1 = self.state.root.outputs.lock().values().map(|o| o.position.get().x2()).max().unwrap_or(0); let global = Rc::new(WlOutputGlobal::new(name, self.output.clone(), x1));
let on = Rc::new(OutputNode { let on = Rc::new(OutputNode {
id: self.state.node_ids.next(), id: self.state.node_ids.next(),
workspaces: Default::default(), workspaces: Default::default(),
position: Cell::new(Rect::new_empty(x1, 0)),
workspace: CloneCell::new(None), workspace: CloneCell::new(None),
seat_state: Default::default(), seat_state: Default::default(),
global: global.clone(), global: global.clone(),
@ -68,20 +67,15 @@ impl OutputHandler {
self.state.root.outputs.set(self.output.id(), on.clone()); self.state.root.outputs.set(self.output.id(), on.clone());
self.state.add_global(&global); self.state.add_global(&global);
self.state.outputs.set(self.output.id(), global.clone()); self.state.outputs.set(self.output.id(), global.clone());
let mut width = 0; 'outer: loop {
let mut height = 0; while let Some(event) = self.output.event() {
loop { match event {
if self.output.removed() { ConnectorEvent::Removed => break 'outer,
break; ConnectorEvent::ModeChanged(mode) => {
on.update_mode(mode);
}
}
} }
let new_width = self.output.width();
let new_height = self.output.height();
if new_width != width || new_height != height {
width = new_width;
height = new_height;
on.change_size(new_width, new_height);
}
global.update_properties();
ae.triggered().await; ae.triggered().await;
} }
global.node.set(None); global.node.set(None);

View file

@ -434,7 +434,7 @@ impl Node for DisplayNode {
} }
let outputs = self.outputs.lock(); let outputs = self.outputs.lock();
for output in outputs.values() { for output in outputs.values() {
let pos = output.position.get(); let pos = output.global.pos.get();
if pos.contains(x, y) { if pos.contains(x, y) {
let (x, y) = pos.translate(x, y); let (x, y) = pos.translate(x, y);
tree.push(FoundNode { tree.push(FoundNode {

View file

@ -13,15 +13,15 @@ use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode};
use crate::utils::clonecell::CloneCell; use crate::utils::clonecell::CloneCell;
use crate::utils::errorfmt::ErrorFmt; use crate::utils::errorfmt::ErrorFmt;
use crate::utils::linkedlist::LinkedList; use crate::utils::linkedlist::LinkedList;
use std::cell::{Cell, RefCell}; use std::cell::{RefCell};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::ops::{Deref, Sub}; use std::ops::{Deref, Sub};
use std::rc::Rc; use std::rc::Rc;
use crate::backend::Mode;
tree_id!(OutputNodeId); tree_id!(OutputNodeId);
pub struct OutputNode { pub struct OutputNode {
pub id: OutputNodeId, pub id: OutputNodeId,
pub position: Cell<Rect>,
pub global: Rc<WlOutputGlobal>, pub global: Rc<WlOutputGlobal>,
pub workspaces: LinkedList<Rc<WorkspaceNode>>, pub workspaces: LinkedList<Rc<WorkspaceNode>>,
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>, pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
@ -84,7 +84,7 @@ impl OutputNode {
} }
fn workspace_rect(&self) -> Rect { fn workspace_rect(&self) -> Rect {
let rect = self.position.get(); let rect = self.global.pos.get();
let th = self.state.theme.title_height.get(); let th = self.state.theme.title_height.get();
Rect::new_sized( Rect::new_sized(
rect.x1(), rect.x1(),
@ -95,10 +95,13 @@ impl OutputNode {
.unwrap() .unwrap()
} }
pub fn change_size(&self, width: i32, height: i32) { pub fn update_mode(&self, mode: Mode) {
let pos = self.position.get(); if self.global.mode.get() == mode {
let rect = Rect::new_sized(pos.x1(), pos.y1(), width, height).unwrap(); return;
self.position.set(rect); }
let pos = self.global.pos.get();
let rect = Rect::new_sized(pos.x1(), pos.y1(), mode.width, mode.height).unwrap();
self.global.pos.set(rect);
if let Some(c) = self.workspace.get() { if let Some(c) = self.workspace.get() {
c.change_extents(&self.workspace_rect()); c.change_extents(&self.workspace_rect());
} }
@ -107,6 +110,7 @@ impl OutputNode {
surface.deref().clone().change_extents(&rect); surface.deref().clone().change_extents(&rect);
} }
} }
self.global.send_mode();
} }
} }
@ -166,7 +170,7 @@ impl Node for OutputNode {
} }
fn absolute_position(&self) -> Rect { fn absolute_position(&self) -> Rect {
self.position.get() self.global.pos.get()
} }
fn find_tree_at(&self, x: i32, mut y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult { fn find_tree_at(&self, x: i32, mut y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {

View file

@ -1,4 +1,4 @@
use crate::utils::ptr_ext::MutPtrExt; use crate::utils::ptr_ext::{MutPtrExt, PtrExt};
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
pub struct Stack<T> { pub struct Stack<T> {
@ -23,4 +23,13 @@ impl<T> Stack<T> {
pub fn pop(&self) -> Option<T> { pub fn pop(&self) -> Option<T> {
unsafe { self.vec.get().deref_mut().pop() } unsafe { self.vec.get().deref_mut().pop() }
} }
pub fn to_vec(&self) -> Vec<T>
where T: Clone,
{
unsafe {
let v = self.vec.get().deref();
(*v).clone()
}
}
} }

View file

@ -3,6 +3,7 @@ use std::cell::UnsafeCell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::mem; use std::mem;
#[derive(Debug)]
pub struct SyncQueue<T> { pub struct SyncQueue<T> {
el: UnsafeCell<VecDeque<T>>, el: UnsafeCell<VecDeque<T>>,
} }