autocommit 2022-04-04 00:28:58 CEST
This commit is contained in:
parent
9ec1c5c995
commit
1f71290dab
21 changed files with 1217 additions and 132 deletions
|
|
@ -9,14 +9,25 @@ pub trait Backend {
|
|||
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 removed(&self) -> bool;
|
||||
fn width(&self) -> i32;
|
||||
fn height(&self) -> i32;
|
||||
fn event(&self) -> Option<ConnectorEvent>;
|
||||
fn on_change(&self, cb: Rc<dyn Fn()>);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ConnectorEvent {
|
||||
Removed,
|
||||
ModeChanged(Mode),
|
||||
}
|
||||
|
||||
pub trait InputDevice {
|
||||
fn id(&self) -> InputDeviceId;
|
||||
fn removed(&self) -> bool;
|
||||
|
|
@ -49,7 +60,7 @@ pub enum InputDeviceAccelProfile {
|
|||
}
|
||||
|
||||
pub enum BackendEvent {
|
||||
NewOutput(Rc<dyn Output>),
|
||||
NewConnector(Rc<dyn Connector>),
|
||||
NewInputDevice(Rc<dyn InputDevice>),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::backend::{Backend, Output, OutputId};
|
||||
use crate::backend::{Backend, Connector, ConnectorEvent, OutputId};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct DummyBackend {}
|
||||
|
|
@ -13,21 +13,13 @@ pub struct DummyOutput {
|
|||
pub id: OutputId,
|
||||
}
|
||||
|
||||
impl Output for DummyOutput {
|
||||
impl Connector for DummyOutput {
|
||||
fn id(&self) -> OutputId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn removed(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn width(&self) -> i32 {
|
||||
100
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
100
|
||||
fn event(&self) -> Option<ConnectorEvent> {
|
||||
None
|
||||
}
|
||||
|
||||
fn on_change(&self, _cb: Rc<dyn Fn()>) {
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ impl MetalBackend {
|
|||
}
|
||||
|
||||
fn handle_drm_change(self: &Rc<Self>, _dev: UdevDevice) -> Option<()> {
|
||||
// TODO: Handle monitor connections and connector hotplug
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
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::drm::drm::{
|
||||
drm_mode_modeinfo, Change, ConnectorStatus, ConnectorType, DrmBlob, DrmConnector, DrmCrtc,
|
||||
|
|
@ -24,6 +24,7 @@ use std::ffi::CString;
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
use uapi::c;
|
||||
use crate::utils::syncqueue::SyncQueue;
|
||||
|
||||
pub struct PendingDrmDevice {
|
||||
pub id: DrmId,
|
||||
|
|
@ -77,6 +78,8 @@ pub struct MetalConnector {
|
|||
pub modes: Vec<DrmModeInfo>,
|
||||
pub mode: CloneCell<Option<Rc<DrmModeInfo>>>,
|
||||
|
||||
pub events: SyncQueue<ConnectorEvent>,
|
||||
|
||||
pub buffers: CloneCell<Option<Rc<[RenderBuffer; 2]>>>,
|
||||
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 {
|
||||
self.output_id
|
||||
}
|
||||
|
||||
fn removed(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
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 event(&self) -> Option<ConnectorEvent> {
|
||||
self.events.pop()
|
||||
}
|
||||
|
||||
fn on_change(&self, cb: Rc<dyn Fn()>) {
|
||||
|
|
@ -223,12 +212,22 @@ fn create_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 {
|
||||
id: connector,
|
||||
master: dev.master.clone(),
|
||||
output_id: state.output_ids.next(),
|
||||
crtcs,
|
||||
mode: CloneCell::new(info.modes.first().cloned().map(Rc::new)),
|
||||
mode: CloneCell::new(mode),
|
||||
events,
|
||||
modes: info.modes,
|
||||
buffers: Default::default(),
|
||||
next_buffer: Default::default(),
|
||||
|
|
@ -486,6 +485,9 @@ impl MetalBackend {
|
|||
self.init_drm_device(&slf)?;
|
||||
|
||||
for connector in slf.connectors.values() {
|
||||
self.state
|
||||
.backend_events
|
||||
.push(BackendEvent::NewConnector(connector.clone()));
|
||||
if connector.primary_plane.get().is_some() {
|
||||
self.start_connector(connector);
|
||||
}
|
||||
|
|
@ -880,9 +882,6 @@ impl MetalBackend {
|
|||
|
||||
fn start_connector(&self, connector: &Rc<MetalConnector>) {
|
||||
let mode = connector.mode.get().unwrap();
|
||||
self.state
|
||||
.backend_events
|
||||
.push(BackendEvent::NewOutput(connector.clone()));
|
||||
log::info!(
|
||||
"Initialized connector {}-{} with mode {:?}",
|
||||
connector.connector_type,
|
||||
|
|
@ -905,7 +904,7 @@ impl MetalBackend {
|
|||
if let Some(node) = self.state.root.outputs.get(&connector.output_id) {
|
||||
buffer
|
||||
.egl
|
||||
.render(&*node, &self.state, Some(node.position.get()));
|
||||
.render(&*node, &self.state, Some(node.global.pos.get()));
|
||||
}
|
||||
let mut changes = connector.master.change();
|
||||
changes.change_object(plane.id, |c| {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
use crate::async_engine::{Phase, SpawnedFuture};
|
||||
use crate::backend::{
|
||||
Backend, BackendEvent, InputDevice, InputDeviceAccelProfile, InputDeviceCapability,
|
||||
InputDeviceId, InputEvent, KeyState, Output, OutputId, ScrollAxis,
|
||||
};
|
||||
use crate::backend::{Backend, BackendEvent, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent, KeyState, Connector, OutputId, ScrollAxis, Mode, ConnectorEvent};
|
||||
use crate::drm::drm::{Drm, DrmError};
|
||||
use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
|
||||
use crate::drm::{ModifiedFormat, INVALID_MODIFIER};
|
||||
|
|
@ -42,6 +39,7 @@ use std::cell::{Cell, RefCell};
|
|||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::utils::syncqueue::SyncQueue;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum XBackendError {
|
||||
|
|
@ -396,7 +394,7 @@ impl XBackendData {
|
|||
id: self.state.output_ids.next(),
|
||||
_backend: self.clone(),
|
||||
window: window_id,
|
||||
removed: Cell::new(false),
|
||||
events: Default::default(),
|
||||
width: Cell::new(0),
|
||||
height: Cell::new(0),
|
||||
serial: Default::default(),
|
||||
|
|
@ -479,7 +477,7 @@ impl XBackendData {
|
|||
self.outputs.set(window_id, output.clone());
|
||||
self.state
|
||||
.backend_events
|
||||
.push(BackendEvent::NewOutput(output.clone()));
|
||||
.push(BackendEvent::NewConnector(output.clone()));
|
||||
self.present(&output).await;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -636,10 +634,6 @@ impl XBackendData {
|
|||
}
|
||||
|
||||
async fn present(&self, output: &Rc<XOutput>) {
|
||||
if output.removed.get() {
|
||||
return;
|
||||
}
|
||||
|
||||
let serial = output.serial.fetch_add(1);
|
||||
|
||||
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) {
|
||||
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 {
|
||||
|
|
@ -795,7 +789,7 @@ impl XBackendData {
|
|||
Some(o) => o,
|
||||
_ => return Ok(()),
|
||||
};
|
||||
output.removed.set(true);
|
||||
output.events.push(ConnectorEvent::Removed);
|
||||
output.changed();
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -820,6 +814,11 @@ impl XBackendData {
|
|||
old.fb.set(new.fb.get());
|
||||
old.pixmap.set(new.pixmap.get());
|
||||
}
|
||||
output.events.push(ConnectorEvent::ModeChanged(Mode {
|
||||
width,
|
||||
height,
|
||||
refresh_rate: 60, // TODO
|
||||
}));
|
||||
output.changed();
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -830,7 +829,7 @@ struct XOutput {
|
|||
id: OutputId,
|
||||
_backend: Rc<XBackendData>,
|
||||
window: u32,
|
||||
removed: Cell<bool>,
|
||||
events: SyncQueue<ConnectorEvent>,
|
||||
width: Cell<i32>,
|
||||
height: Cell<i32>,
|
||||
serial: NumCell<u32>,
|
||||
|
|
@ -856,21 +855,13 @@ impl XOutput {
|
|||
}
|
||||
}
|
||||
|
||||
impl Output for XOutput {
|
||||
impl Connector for XOutput {
|
||||
fn id(&self) -> OutputId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn removed(&self) -> bool {
|
||||
self.removed.get()
|
||||
}
|
||||
|
||||
fn width(&self) -> i32 {
|
||||
self.width.get()
|
||||
}
|
||||
|
||||
fn height(&self) -> i32 {
|
||||
self.height.get()
|
||||
fn event(&self) -> Option<ConnectorEvent> {
|
||||
self.events.pop()
|
||||
}
|
||||
|
||||
fn on_change(&self, cb: Rc<dyn Fn()>) {
|
||||
|
|
|
|||
|
|
@ -120,12 +120,12 @@ fn main_(logger: Arc<Logger>, _args: &RunArgs) -> Result<(), MainError> {
|
|||
{
|
||||
let dummy_output = Rc::new(OutputNode {
|
||||
id: state.node_ids.next(),
|
||||
position: Default::default(),
|
||||
global: Rc::new(WlOutputGlobal::new(
|
||||
state.globals.name(),
|
||||
Rc::new(DummyOutput {
|
||||
id: state.output_ids.next(),
|
||||
}),
|
||||
0,
|
||||
)),
|
||||
workspaces: Default::default(),
|
||||
workspace: Default::default(),
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ pub use sys::{
|
|||
drm_mode_modeinfo, DRM_CLIENT_CAP_ATOMIC, DRM_MODE_ATOMIC_ALLOW_MODESET,
|
||||
DRM_MODE_ATOMIC_NONBLOCK, DRM_MODE_PAGE_FLIP_EVENT,
|
||||
};
|
||||
use crate::utils::vec_ext::VecExt;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DrmError {
|
||||
|
|
@ -63,6 +64,8 @@ pub enum DrmError {
|
|||
GetPropBlob(#[source] OsError),
|
||||
#[error("Property has an invalid size")]
|
||||
InvalidProbSize,
|
||||
#[error("Property has a size that is not a multiple of the vector type")]
|
||||
UnalignedPropSize,
|
||||
#[error("Could not perform drm properties ioctl")]
|
||||
GetProperties(#[source] OsError),
|
||||
#[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> {
|
||||
if self.events.is_empty() {
|
||||
let mut buf = self.buf.borrow_mut();
|
||||
|
|
@ -570,6 +592,16 @@ impl DrmModeInfo {
|
|||
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)]
|
||||
|
|
|
|||
1059
src/edid.rs
Normal file
1059
src/edid.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
use crate::backend::Output;
|
||||
use crate::backend::Connector;
|
||||
use crate::client::{Client, ClientError, ClientId};
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::zxdg_output_v1::ZxdgOutputV1;
|
||||
|
|
@ -17,6 +17,7 @@ use std::cell::{Cell, RefCell};
|
|||
use std::collections::hash_map::Entry;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::backend;
|
||||
|
||||
const SP_UNKNOWN: i32 = 0;
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -52,18 +53,20 @@ const MODE_PREFERRED: u32 = 2;
|
|||
|
||||
pub struct WlOutputGlobal {
|
||||
name: GlobalName,
|
||||
output: Rc<dyn Output>,
|
||||
pos: Cell<Rect>,
|
||||
pub connector: Rc<dyn Connector>,
|
||||
pub pos: Cell<Rect>,
|
||||
pub mode: Cell<backend::Mode>,
|
||||
pub node: CloneCell<Option<Rc<OutputNode>>>,
|
||||
pub bindings: RefCell<AHashMap<ClientId, AHashMap<WlOutputId, Rc<WlOutput>>>>,
|
||||
}
|
||||
|
||||
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 {
|
||||
name,
|
||||
output: output.clone(),
|
||||
pos: Cell::new(Rect::new_sized(0, 0, output.width(), output.height()).unwrap()),
|
||||
connector: connector.clone(),
|
||||
pos: Cell::new(Rect::new_empty(x1, 0)),
|
||||
mode: Default::default(),
|
||||
node: Default::default(),
|
||||
bindings: Default::default(),
|
||||
}
|
||||
|
|
@ -73,30 +76,18 @@ impl WlOutputGlobal {
|
|||
self.pos.get()
|
||||
}
|
||||
|
||||
pub fn update_properties(&self) {
|
||||
let width = self.output.width();
|
||||
let height = self.output.height();
|
||||
|
||||
let pos = self.pos.get();
|
||||
let old_width = pos.width();
|
||||
let old_height = pos.height();
|
||||
let changed = old_width != width || old_height != height;
|
||||
|
||||
if changed {
|
||||
self.pos
|
||||
.set(Rect::new_sized(pos.x1(), pos.y1(), width, height).unwrap());
|
||||
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();
|
||||
}
|
||||
pub fn send_mode(&self) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ impl XdgPopup {
|
|||
let mut rel_pos = positioner.get_position(false, false);
|
||||
let mut abs_pos = rel_pos.move_(parent_abs.x1(), parent_abs.y1());
|
||||
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);
|
||||
if !overflow.is_contained() {
|
||||
let mut flip_x = positioner.ca.contains(CA::FLIP_X) && overflow.x_overflow();
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ impl ZwlrLayerSurfaceV1 {
|
|||
if anchor == 0 {
|
||||
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 y1 = opos.y1();
|
||||
if anchor.contains(LEFT) {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ impl ZwlrLayerShellV1 {
|
|||
}
|
||||
}
|
||||
};
|
||||
log::info!("output = {:?}", output.position.get());
|
||||
log::info!("output = {:?}", output.global.pos.get());
|
||||
if req.layer > OVERLAY {
|
||||
return Err(GetLayerSurfaceError::UnknownLayer(req.layer));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ mod wire_xcon;
|
|||
mod xcon;
|
||||
mod xkbcommon;
|
||||
mod xwayland;
|
||||
mod edid;
|
||||
|
||||
fn main() {
|
||||
cli::main();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ pub struct Renderer<'a> {
|
|||
|
||||
impl Renderer<'_> {
|
||||
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 {
|
||||
($layer:expr) => {
|
||||
for ls in $layer.iter() {
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ impl State {
|
|||
width += 2 * self.theme.border_width.get();
|
||||
height += 2 * self.theme.border_width.get() + self.theme.title_height.get();
|
||||
let output = workspace.output.get();
|
||||
let output_rect = output.position.get();
|
||||
let output_rect = output.global.pos.get();
|
||||
let position = {
|
||||
let mut x1 = output_rect.x1();
|
||||
let mut y1 = output_rect.y1();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::backend::{BackendEvent, Output};
|
||||
use crate::backend::{BackendEvent, Connector};
|
||||
use crate::state::State;
|
||||
use crate::tasks::input_device;
|
||||
use crate::tasks::output::OutputHandler;
|
||||
|
|
@ -18,12 +18,12 @@ impl BackendEventHandler {
|
|||
|
||||
fn handle_event(&mut self, event: BackendEvent) {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
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 oh = OutputHandler {
|
||||
state: self.state.clone(),
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
use crate::backend::Output;
|
||||
use crate::backend::{Connector, ConnectorEvent};
|
||||
use crate::ifs::wl_output::WlOutputGlobal;
|
||||
use crate::rect::Rect;
|
||||
use crate::state::State;
|
||||
use crate::tree::{OutputNode, OutputRenderData, WorkspaceNode};
|
||||
use crate::utils::asyncevent::AsyncEvent;
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::cell::{RefCell};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct OutputHandler {
|
||||
pub state: Rc<State>,
|
||||
pub output: Rc<dyn Output>,
|
||||
pub output: Rc<dyn Connector>,
|
||||
}
|
||||
|
||||
impl OutputHandler {
|
||||
|
|
@ -21,12 +21,11 @@ impl OutputHandler {
|
|||
self.output.on_change(Rc::new(move || ae.trigger()));
|
||||
}
|
||||
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.position.get().x2()).max().unwrap_or(0);
|
||||
let x1 = self.state.root.outputs.lock().values().map(|o| o.global.pos.get().x2()).max().unwrap_or(0);
|
||||
let global = Rc::new(WlOutputGlobal::new(name, self.output.clone(), x1));
|
||||
let on = Rc::new(OutputNode {
|
||||
id: self.state.node_ids.next(),
|
||||
workspaces: Default::default(),
|
||||
position: Cell::new(Rect::new_empty(x1, 0)),
|
||||
workspace: CloneCell::new(None),
|
||||
seat_state: Default::default(),
|
||||
global: global.clone(),
|
||||
|
|
@ -68,20 +67,15 @@ impl OutputHandler {
|
|||
self.state.root.outputs.set(self.output.id(), on.clone());
|
||||
self.state.add_global(&global);
|
||||
self.state.outputs.set(self.output.id(), global.clone());
|
||||
let mut width = 0;
|
||||
let mut height = 0;
|
||||
loop {
|
||||
if self.output.removed() {
|
||||
break;
|
||||
'outer: loop {
|
||||
while let Some(event) = self.output.event() {
|
||||
match event {
|
||||
ConnectorEvent::Removed => break 'outer,
|
||||
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;
|
||||
}
|
||||
global.node.set(None);
|
||||
|
|
|
|||
|
|
@ -434,7 +434,7 @@ impl Node for DisplayNode {
|
|||
}
|
||||
let outputs = self.outputs.lock();
|
||||
for output in outputs.values() {
|
||||
let pos = output.position.get();
|
||||
let pos = output.global.pos.get();
|
||||
if pos.contains(x, y) {
|
||||
let (x, y) = pos.translate(x, y);
|
||||
tree.push(FoundNode {
|
||||
|
|
|
|||
|
|
@ -13,15 +13,15 @@ use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode};
|
|||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::errorfmt::ErrorFmt;
|
||||
use crate::utils::linkedlist::LinkedList;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::cell::{RefCell};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::ops::{Deref, Sub};
|
||||
use std::rc::Rc;
|
||||
use crate::backend::Mode;
|
||||
|
||||
tree_id!(OutputNodeId);
|
||||
pub struct OutputNode {
|
||||
pub id: OutputNodeId,
|
||||
pub position: Cell<Rect>,
|
||||
pub global: Rc<WlOutputGlobal>,
|
||||
pub workspaces: LinkedList<Rc<WorkspaceNode>>,
|
||||
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
||||
|
|
@ -84,7 +84,7 @@ impl OutputNode {
|
|||
}
|
||||
|
||||
fn workspace_rect(&self) -> Rect {
|
||||
let rect = self.position.get();
|
||||
let rect = self.global.pos.get();
|
||||
let th = self.state.theme.title_height.get();
|
||||
Rect::new_sized(
|
||||
rect.x1(),
|
||||
|
|
@ -95,10 +95,13 @@ impl OutputNode {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn change_size(&self, width: i32, height: i32) {
|
||||
let pos = self.position.get();
|
||||
let rect = Rect::new_sized(pos.x1(), pos.y1(), width, height).unwrap();
|
||||
self.position.set(rect);
|
||||
pub fn update_mode(&self, mode: Mode) {
|
||||
if self.global.mode.get() == mode {
|
||||
return;
|
||||
}
|
||||
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() {
|
||||
c.change_extents(&self.workspace_rect());
|
||||
}
|
||||
|
|
@ -107,6 +110,7 @@ impl OutputNode {
|
|||
surface.deref().clone().change_extents(&rect);
|
||||
}
|
||||
}
|
||||
self.global.send_mode();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +170,7 @@ impl Node for OutputNode {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::utils::ptr_ext::MutPtrExt;
|
||||
use crate::utils::ptr_ext::{MutPtrExt, PtrExt};
|
||||
use std::cell::UnsafeCell;
|
||||
|
||||
pub struct Stack<T> {
|
||||
|
|
@ -23,4 +23,13 @@ impl<T> Stack<T> {
|
|||
pub fn pop(&self) -> Option<T> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::cell::UnsafeCell;
|
|||
use std::collections::VecDeque;
|
||||
use std::mem;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SyncQueue<T> {
|
||||
el: UnsafeCell<VecDeque<T>>,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue