tree: make scale and position of outputs persistent
This commit is contained in:
parent
bc9b1c3638
commit
3eb0f61ec1
16 changed files with 135 additions and 84 deletions
|
|
@ -602,10 +602,10 @@ impl MetalConnector {
|
||||||
&self.state,
|
&self.state,
|
||||||
Some(output.global.pos.get()),
|
Some(output.global.pos.get()),
|
||||||
Some(rr),
|
Some(rr),
|
||||||
output.global.preferred_scale.get(),
|
output.global.persistent.scale.get(),
|
||||||
render_hw_cursor,
|
render_hw_cursor,
|
||||||
output.has_fullscreen(),
|
output.has_fullscreen(),
|
||||||
output.global.transform.get(),
|
output.global.persistent.transform.get(),
|
||||||
);
|
);
|
||||||
let try_direct_scanout = try_direct_scanout
|
let try_direct_scanout = try_direct_scanout
|
||||||
&& self.direct_scanout_enabled()
|
&& self.direct_scanout_enabled()
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,10 @@ use {
|
||||||
dbus::Dbus,
|
dbus::Dbus,
|
||||||
forker,
|
forker,
|
||||||
globals::Globals,
|
globals::Globals,
|
||||||
ifs::{wl_output::WlOutputGlobal, wl_surface::NoneSurfaceExt},
|
ifs::{
|
||||||
|
wl_output::{OutputId, PersistentOutputState, WlOutputGlobal},
|
||||||
|
wl_surface::NoneSurfaceExt,
|
||||||
|
},
|
||||||
io_uring::{IoUring, IoUringError},
|
io_uring::{IoUring, IoUringError},
|
||||||
leaks,
|
leaks,
|
||||||
logger::Logger,
|
logger::Logger,
|
||||||
|
|
@ -204,7 +207,7 @@ fn start_compositor2(
|
||||||
dma_buf_ids: Default::default(),
|
dma_buf_ids: Default::default(),
|
||||||
drm_feedback_ids: Default::default(),
|
drm_feedback_ids: Default::default(),
|
||||||
direct_scanout_enabled: Cell::new(true),
|
direct_scanout_enabled: Cell::new(true),
|
||||||
output_transforms: Default::default(),
|
persistent_output_states: Default::default(),
|
||||||
double_click_interval_usec: Cell::new(400 * 1000),
|
double_click_interval_usec: Cell::new(400 * 1000),
|
||||||
double_click_distance: Cell::new(5),
|
double_click_distance: Cell::new(5),
|
||||||
create_default_seat: Cell::new(true),
|
create_default_seat: Cell::new(true),
|
||||||
|
|
@ -364,6 +367,17 @@ fn init_fd_limit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_dummy_output(state: &Rc<State>) {
|
fn create_dummy_output(state: &Rc<State>) {
|
||||||
|
let output_id = Rc::new(OutputId {
|
||||||
|
connector: "jay-dummy-connector".to_string(),
|
||||||
|
manufacturer: "jay".to_string(),
|
||||||
|
model: "jay-dummy-output".to_string(),
|
||||||
|
serial_number: "".to_string(),
|
||||||
|
});
|
||||||
|
let persistent_state = Rc::new(PersistentOutputState {
|
||||||
|
transform: Default::default(),
|
||||||
|
scale: Default::default(),
|
||||||
|
pos: Default::default(),
|
||||||
|
});
|
||||||
let dummy_output = Rc::new(OutputNode {
|
let dummy_output = Rc::new(OutputNode {
|
||||||
id: state.node_ids.next(),
|
id: state.node_ids.next(),
|
||||||
global: Rc::new(WlOutputGlobal::new(
|
global: Rc::new(WlOutputGlobal::new(
|
||||||
|
|
@ -379,18 +393,16 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
drm_dev: None,
|
drm_dev: None,
|
||||||
async_event: Default::default(),
|
async_event: Default::default(),
|
||||||
}),
|
}),
|
||||||
0,
|
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
&backend::Mode {
|
&backend::Mode {
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
refresh_rate_millihz: 0,
|
refresh_rate_millihz: 0,
|
||||||
},
|
},
|
||||||
"jay",
|
|
||||||
"dummy-output",
|
|
||||||
"0",
|
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
&output_id,
|
||||||
|
&persistent_state,
|
||||||
)),
|
)),
|
||||||
jay_outputs: Default::default(),
|
jay_outputs: Default::default(),
|
||||||
workspaces: Default::default(),
|
workspaces: Default::default(),
|
||||||
|
|
|
||||||
|
|
@ -793,7 +793,7 @@ impl ConfigProxyHandler {
|
||||||
fn handle_connector_get_scale(&self, connector: Connector) -> Result<(), CphError> {
|
fn handle_connector_get_scale(&self, connector: Connector) -> Result<(), CphError> {
|
||||||
let connector = self.get_output(connector)?;
|
let connector = self.get_output(connector)?;
|
||||||
self.respond(Response::ConnectorGetScale {
|
self.respond(Response::ConnectorGetScale {
|
||||||
scale: connector.node.global.preferred_scale.get().to_f64(),
|
scale: connector.node.global.persistent.scale.get().to_f64(),
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@ impl dyn GfxFramebuffer {
|
||||||
scale,
|
scale,
|
||||||
render_hardware_cursor,
|
render_hardware_cursor,
|
||||||
node.has_fullscreen(),
|
node.has_fullscreen(),
|
||||||
node.global.transform.get(),
|
node.global.persistent.transform.get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,12 +92,12 @@ impl JayRandr {
|
||||||
let pos = global.pos.get();
|
let pos = global.pos.get();
|
||||||
self.client.event(Output {
|
self.client.event(Output {
|
||||||
self_id: self.id,
|
self_id: self.id,
|
||||||
scale: global.preferred_scale.get().to_wl(),
|
scale: global.persistent.scale.get().to_wl(),
|
||||||
width: pos.width(),
|
width: pos.width(),
|
||||||
height: pos.height(),
|
height: pos.height(),
|
||||||
x: pos.x1(),
|
x: pos.x1(),
|
||||||
y: pos.y1(),
|
y: pos.y1(),
|
||||||
transform: global.transform.get().to_wl(),
|
transform: global.persistent.transform.get().to_wl(),
|
||||||
manufacturer: &output.monitor_info.manufacturer,
|
manufacturer: &output.monitor_info.manufacturer,
|
||||||
product: &output.monitor_info.product,
|
product: &output.monitor_info.product,
|
||||||
serial_number: &output.monitor_info.serial_number,
|
serial_number: &output.monitor_info.serial_number,
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ impl JayScreencast {
|
||||||
x_off,
|
x_off,
|
||||||
y_off,
|
y_off,
|
||||||
size,
|
size,
|
||||||
on.global.transform.get(),
|
on.global.persistent.transform.get(),
|
||||||
);
|
);
|
||||||
self.client.event(Ready {
|
self.client.event(Ready {
|
||||||
self_id: self.id,
|
self_id: self.id,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use {
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
state::{ConnectorData, State},
|
state::{ConnectorData, State},
|
||||||
time::Time,
|
time::Time,
|
||||||
tree::OutputNode,
|
tree::{calculate_logical_size, OutputNode},
|
||||||
utils::{
|
utils::{
|
||||||
buffd::{MsgParser, MsgParserError},
|
buffd::{MsgParser, MsgParserError},
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
|
|
@ -75,12 +75,18 @@ pub struct WlOutputGlobal {
|
||||||
pub pending_captures: LinkedList<Rc<ZwlrScreencopyFrameV1>>,
|
pub pending_captures: LinkedList<Rc<ZwlrScreencopyFrameV1>>,
|
||||||
pub destroyed: Cell<bool>,
|
pub destroyed: Cell<bool>,
|
||||||
pub legacy_scale: Cell<u32>,
|
pub legacy_scale: Cell<u32>,
|
||||||
pub preferred_scale: Cell<crate::scale::Scale>,
|
pub persistent: Rc<PersistentOutputState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PersistentOutputState {
|
||||||
pub transform: Cell<Transform>,
|
pub transform: Cell<Transform>,
|
||||||
|
pub scale: Cell<crate::scale::Scale>,
|
||||||
|
pub pos: Cell<(i32, i32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash)]
|
#[derive(Eq, PartialEq, Hash)]
|
||||||
pub struct OutputId {
|
pub struct OutputId {
|
||||||
|
pub connector: String,
|
||||||
pub manufacturer: String,
|
pub manufacturer: String,
|
||||||
pub model: String,
|
pub model: String,
|
||||||
pub serial_number: String,
|
pub serial_number: String,
|
||||||
|
|
@ -96,33 +102,26 @@ impl WlOutputGlobal {
|
||||||
name: GlobalName,
|
name: GlobalName,
|
||||||
state: &Rc<State>,
|
state: &Rc<State>,
|
||||||
connector: &Rc<ConnectorData>,
|
connector: &Rc<ConnectorData>,
|
||||||
x1: i32,
|
|
||||||
modes: Vec<backend::Mode>,
|
modes: Vec<backend::Mode>,
|
||||||
mode: &backend::Mode,
|
mode: &backend::Mode,
|
||||||
manufacturer: &str,
|
|
||||||
product: &str,
|
|
||||||
serial_number: &str,
|
|
||||||
width_mm: i32,
|
width_mm: i32,
|
||||||
height_mm: i32,
|
height_mm: i32,
|
||||||
|
output_id: &Rc<OutputId>,
|
||||||
|
persistent_state: &Rc<PersistentOutputState>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let output_id = Rc::new(OutputId {
|
let (x, y) = persistent_state.pos.get();
|
||||||
manufacturer: manufacturer.to_string(),
|
let scale = persistent_state.scale.get();
|
||||||
model: product.to_string(),
|
let (width, height) = calculate_logical_size(
|
||||||
serial_number: serial_number.to_string(),
|
(mode.width, mode.height),
|
||||||
});
|
persistent_state.transform.get(),
|
||||||
let transform = state
|
scale,
|
||||||
.output_transforms
|
);
|
||||||
.borrow()
|
|
||||||
.get(&output_id)
|
|
||||||
.copied()
|
|
||||||
.unwrap_or(Transform::None);
|
|
||||||
let (width, height) = transform.maybe_swap((mode.width, mode.height));
|
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
connector: connector.clone(),
|
connector: connector.clone(),
|
||||||
pos: Cell::new(Rect::new_sized(x1, 0, width, height).unwrap()),
|
pos: Cell::new(Rect::new_sized(x, y, width, height).unwrap()),
|
||||||
output_id,
|
output_id: output_id.clone(),
|
||||||
mode: Cell::new(*mode),
|
mode: Cell::new(*mode),
|
||||||
modes,
|
modes,
|
||||||
node: Default::default(),
|
node: Default::default(),
|
||||||
|
|
@ -132,9 +131,8 @@ impl WlOutputGlobal {
|
||||||
unused_captures: Default::default(),
|
unused_captures: Default::default(),
|
||||||
pending_captures: Default::default(),
|
pending_captures: Default::default(),
|
||||||
destroyed: Cell::new(false),
|
destroyed: Cell::new(false),
|
||||||
legacy_scale: Cell::new(1),
|
legacy_scale: Cell::new(scale.round_up()),
|
||||||
preferred_scale: Cell::new(crate::scale::Scale::from_int(1)),
|
persistent: persistent_state.clone(),
|
||||||
transform: Cell::new(transform),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -289,7 +287,10 @@ impl WlOutputGlobal {
|
||||||
|
|
||||||
pub fn pixel_size(&self) -> (i32, i32) {
|
pub fn pixel_size(&self) -> (i32, i32) {
|
||||||
let mode = self.mode.get();
|
let mode = self.mode.get();
|
||||||
self.transform.get().maybe_swap((mode.width, mode.height))
|
self.persistent
|
||||||
|
.transform
|
||||||
|
.get()
|
||||||
|
.maybe_swap((mode.width, mode.height))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -336,7 +337,7 @@ impl WlOutput {
|
||||||
subpixel: SP_UNKNOWN,
|
subpixel: SP_UNKNOWN,
|
||||||
make: &self.global.output_id.manufacturer,
|
make: &self.global.output_id.manufacturer,
|
||||||
model: &self.global.output_id.model,
|
model: &self.global.output_id.model,
|
||||||
transform: self.global.transform.get().to_wl(),
|
transform: self.global.persistent.transform.get().to_wl(),
|
||||||
};
|
};
|
||||||
self.client.event(event);
|
self.client.event(event);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -272,9 +272,9 @@ impl WlSeatGlobal {
|
||||||
let (x, y) = self.get_position();
|
let (x, y) = self.get_position();
|
||||||
for output in self.state.root.outputs.lock().values() {
|
for output in self.state.root.outputs.lock().values() {
|
||||||
if let Some(hc) = output.hardware_cursor.get() {
|
if let Some(hc) = output.hardware_cursor.get() {
|
||||||
let transform = output.global.transform.get();
|
let transform = output.global.persistent.transform.get();
|
||||||
let render = render | output.hardware_cursor_needs_render.take();
|
let render = render | output.hardware_cursor_needs_render.take();
|
||||||
let scale = output.global.preferred_scale.get();
|
let scale = output.global.persistent.scale.get();
|
||||||
let extents = cursor.extents_at_scale(scale);
|
let extents = cursor.extents_at_scale(scale);
|
||||||
let (hc_width, hc_height) = hc.size();
|
let (hc_width, hc_height) = hc.size();
|
||||||
if render {
|
if render {
|
||||||
|
|
|
||||||
|
|
@ -357,10 +357,10 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
output.global.send_enter(self);
|
output.global.send_enter(self);
|
||||||
old.global.send_leave(self);
|
old.global.send_leave(self);
|
||||||
if old.global.preferred_scale.get() != output.global.preferred_scale.get() {
|
if old.global.persistent.scale.get() != output.global.persistent.scale.get() {
|
||||||
self.on_scale_change();
|
self.on_scale_change();
|
||||||
}
|
}
|
||||||
if old.global.transform.get() != output.global.transform.get() {
|
if old.global.persistent.transform.get() != output.global.persistent.transform.get() {
|
||||||
self.send_preferred_buffer_transform();
|
self.send_preferred_buffer_transform();
|
||||||
}
|
}
|
||||||
let children = self.children.borrow_mut();
|
let children = self.children.borrow_mut();
|
||||||
|
|
@ -459,7 +459,7 @@ impl WlSurface {
|
||||||
if self.version >= TRANSFORM_SINCE {
|
if self.version >= TRANSFORM_SINCE {
|
||||||
self.client.event(PreferredBufferTransform {
|
self.client.event(PreferredBufferTransform {
|
||||||
self_id: self.id,
|
self_id: self.id,
|
||||||
transform: self.output.get().global.transform.get().to_wl() as _,
|
transform: self.output.get().global.persistent.transform.get().to_wl() as _,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,8 @@ impl WpFractionalScaleV1 {
|
||||||
.output
|
.output
|
||||||
.get()
|
.get()
|
||||||
.global
|
.global
|
||||||
.preferred_scale
|
.persistent
|
||||||
|
.scale
|
||||||
.get()
|
.get()
|
||||||
.to_wl(),
|
.to_wl(),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ impl ZwlrScreencopyManagerV1 {
|
||||||
let mode = output.global.mode.get();
|
let mode = output.global.mode.get();
|
||||||
let mut rect = Rect::new_sized(0, 0, mode.width, mode.height).unwrap();
|
let mut rect = Rect::new_sized(0, 0, mode.width, mode.height).unwrap();
|
||||||
if let Some(region) = region {
|
if let Some(region) = region {
|
||||||
let scale = output.global.preferred_scale.get().to_f64();
|
let scale = output.global.persistent.scale.get().to_f64();
|
||||||
let x1 = (region.x1() as f64 * scale).round() as i32;
|
let x1 = (region.x1() as f64 * scale).round() as i32;
|
||||||
let y1 = (region.y1() as f64 * scale).round() as i32;
|
let y1 = (region.y1() as f64 * scale).round() as i32;
|
||||||
let x2 = (region.x2() as f64 * scale).round() as i32;
|
let x2 = (region.x2() as f64 * scale).round() as i32;
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ impl Renderer<'_> {
|
||||||
let c = theme.colors.attention_requested_background.get();
|
let c = theme.colors.attention_requested_background.get();
|
||||||
self.base
|
self.base
|
||||||
.fill_boxes2(&rd.attention_requested_workspaces, &c, x, y);
|
.fill_boxes2(&rd.attention_requested_workspaces, &c, x, y);
|
||||||
let scale = output.global.preferred_scale.get();
|
let scale = output.global.persistent.scale.get();
|
||||||
for title in &rd.titles {
|
for title in &rd.titles {
|
||||||
let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y);
|
let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y);
|
||||||
self.base
|
self.base
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,12 @@ const BASEF: f64 = BASE as f64;
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Scale(u32);
|
pub struct Scale(u32);
|
||||||
|
|
||||||
|
impl Default for Scale {
|
||||||
|
fn default() -> Self {
|
||||||
|
Scale::from_int(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Scale {
|
impl Scale {
|
||||||
pub fn from_int(f: u32) -> Self {
|
pub fn from_int(f: u32) -> Self {
|
||||||
Self(f.saturating_mul(BASE))
|
Self(f.saturating_mul(BASE))
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ use {
|
||||||
jay_seat_events::JaySeatEvents,
|
jay_seat_events::JaySeatEvents,
|
||||||
jay_workspace_watcher::JayWorkspaceWatcher,
|
jay_workspace_watcher::JayWorkspaceWatcher,
|
||||||
wl_drm::WlDrmGlobal,
|
wl_drm::WlDrmGlobal,
|
||||||
wl_output::OutputId,
|
wl_output::{OutputId, PersistentOutputState},
|
||||||
wl_seat::{SeatIds, WlSeatGlobal},
|
wl_seat::{SeatIds, WlSeatGlobal},
|
||||||
wl_surface::{
|
wl_surface::{
|
||||||
zwp_idle_inhibitor_v1::{IdleInhibitorId, IdleInhibitorIds, ZwpIdleInhibitorV1},
|
zwp_idle_inhibitor_v1::{IdleInhibitorId, IdleInhibitorIds, ZwpIdleInhibitorV1},
|
||||||
|
|
@ -153,7 +153,7 @@ pub struct State {
|
||||||
pub dma_buf_ids: DmaBufIds,
|
pub dma_buf_ids: DmaBufIds,
|
||||||
pub drm_feedback_ids: DrmFeedbackIds,
|
pub drm_feedback_ids: DrmFeedbackIds,
|
||||||
pub direct_scanout_enabled: Cell<bool>,
|
pub direct_scanout_enabled: Cell<bool>,
|
||||||
pub output_transforms: RefCell<AHashMap<Rc<OutputId>, Transform>>,
|
pub persistent_output_states: CopyHashMap<Rc<OutputId>, Rc<PersistentOutputState>>,
|
||||||
pub double_click_interval_usec: Cell<u64>,
|
pub double_click_interval_usec: Cell<u64>,
|
||||||
pub double_click_distance: Cell<i32>,
|
pub double_click_distance: Cell<i32>,
|
||||||
pub create_default_seat: Cell<bool>,
|
pub create_default_seat: Cell<bool>,
|
||||||
|
|
@ -772,7 +772,7 @@ impl State {
|
||||||
self,
|
self,
|
||||||
Some(output.global.pos.get()),
|
Some(output.global.pos.get()),
|
||||||
Some(rr),
|
Some(rr),
|
||||||
output.global.preferred_scale.get(),
|
output.global.persistent.scale.get(),
|
||||||
render_hw_cursor,
|
render_hw_cursor,
|
||||||
);
|
);
|
||||||
output.perform_screencopies(tex, !render_hw_cursor, 0, 0, None);
|
output.perform_screencopies(tex, !render_hw_cursor, 0, 0, None);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
backend::{Connector, ConnectorEvent, ConnectorId, MonitorInfo},
|
backend::{Connector, ConnectorEvent, ConnectorId, MonitorInfo},
|
||||||
ifs::wl_output::WlOutputGlobal,
|
ifs::wl_output::{OutputId, PersistentOutputState, WlOutputGlobal},
|
||||||
state::{ConnectorData, OutputData, State},
|
state::{ConnectorData, OutputData, State},
|
||||||
tree::{OutputNode, OutputRenderData},
|
tree::{OutputNode, OutputRenderData},
|
||||||
utils::{asyncevent::AsyncEvent, clonecell::CloneCell},
|
utils::{asyncevent::AsyncEvent, clonecell::CloneCell},
|
||||||
|
|
@ -80,27 +80,45 @@ impl ConnectorHandler {
|
||||||
log::info!("Connector {} connected", self.data.connector.kernel_id());
|
log::info!("Connector {} connected", self.data.connector.kernel_id());
|
||||||
self.data.connected.set(true);
|
self.data.connected.set(true);
|
||||||
let name = self.state.globals.name();
|
let name = self.state.globals.name();
|
||||||
let x1 = self
|
let output_id = Rc::new(OutputId {
|
||||||
.state
|
connector: self.data.name.clone(),
|
||||||
.root
|
manufacturer: info.manufacturer.clone(),
|
||||||
.outputs
|
model: info.product.clone(),
|
||||||
.lock()
|
serial_number: info.serial_number.clone(),
|
||||||
.values()
|
});
|
||||||
.map(|o| o.global.pos.get().x2())
|
let desired_state = match self.state.persistent_output_states.get(&output_id) {
|
||||||
.max()
|
Some(ds) => ds,
|
||||||
.unwrap_or(0);
|
_ => {
|
||||||
|
let x1 = self
|
||||||
|
.state
|
||||||
|
.root
|
||||||
|
.outputs
|
||||||
|
.lock()
|
||||||
|
.values()
|
||||||
|
.map(|o| o.global.pos.get().x2())
|
||||||
|
.max()
|
||||||
|
.unwrap_or(0);
|
||||||
|
let ds = Rc::new(PersistentOutputState {
|
||||||
|
transform: Default::default(),
|
||||||
|
scale: Default::default(),
|
||||||
|
pos: Cell::new((x1, 0)),
|
||||||
|
});
|
||||||
|
self.state
|
||||||
|
.persistent_output_states
|
||||||
|
.set(output_id.clone(), ds.clone());
|
||||||
|
ds
|
||||||
|
}
|
||||||
|
};
|
||||||
let global = Rc::new(WlOutputGlobal::new(
|
let global = Rc::new(WlOutputGlobal::new(
|
||||||
name,
|
name,
|
||||||
&self.state,
|
&self.state,
|
||||||
&self.data,
|
&self.data,
|
||||||
x1,
|
|
||||||
info.modes.clone(),
|
info.modes.clone(),
|
||||||
&info.initial_mode,
|
&info.initial_mode,
|
||||||
&info.manufacturer,
|
|
||||||
&info.product,
|
|
||||||
&info.serial_number,
|
|
||||||
info.width_mm,
|
info.width_mm,
|
||||||
info.height_mm,
|
info.height_mm,
|
||||||
|
&output_id,
|
||||||
|
&desired_state,
|
||||||
));
|
));
|
||||||
let on = Rc::new(OutputNode {
|
let on = Rc::new(OutputNode {
|
||||||
id: self.state.node_ids.next(),
|
id: self.state.node_ids.next(),
|
||||||
|
|
@ -130,8 +148,8 @@ impl ConnectorHandler {
|
||||||
update_render_data_scheduled: Cell::new(false),
|
update_render_data_scheduled: Cell::new(false),
|
||||||
hardware_cursor_needs_render: Cell::new(false),
|
hardware_cursor_needs_render: Cell::new(false),
|
||||||
});
|
});
|
||||||
self.state.add_output_scale(on.global.preferred_scale.get());
|
self.state
|
||||||
let mode = info.initial_mode;
|
.add_output_scale(on.global.persistent.scale.get());
|
||||||
let output_data = Rc::new(OutputData {
|
let output_data = Rc::new(OutputData {
|
||||||
connector: self.data.clone(),
|
connector: self.data.clone(),
|
||||||
monitor_info: info,
|
monitor_info: info,
|
||||||
|
|
@ -140,8 +158,11 @@ impl ConnectorHandler {
|
||||||
self.state.outputs.set(self.id, output_data);
|
self.state.outputs.set(self.id, output_data);
|
||||||
if self.state.outputs.len() == 1 {
|
if self.state.outputs.len() == 1 {
|
||||||
let seats = self.state.globals.seats.lock();
|
let seats = self.state.globals.seats.lock();
|
||||||
|
let pos = global.pos.get();
|
||||||
|
let x = (pos.x1() + pos.x2()) / 2;
|
||||||
|
let y = (pos.y1() + pos.y2()) / 2;
|
||||||
for seat in seats.values() {
|
for seat in seats.values() {
|
||||||
seat.set_position(x1 + mode.width / 2, mode.height / 2);
|
seat.set_position(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
global.node.set(Some(on.clone()));
|
global.node.set(Some(on.clone()));
|
||||||
|
|
@ -277,7 +298,7 @@ impl ConnectorHandler {
|
||||||
dev.connectors.remove(&self.id);
|
dev.connectors.remove(&self.id);
|
||||||
}
|
}
|
||||||
self.state
|
self.state
|
||||||
.remove_output_scale(on.global.preferred_scale.get());
|
.remove_output_scale(on.global.persistent.scale.get());
|
||||||
let _ = self.state.remove_global(&*global);
|
let _ = self.state.remove_global(&*global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ use {
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
||||||
linkedlist::LinkedList, scroller::Scroller,
|
linkedlist::LinkedList, scroller::Scroller, transform_ext::TransformExt,
|
||||||
},
|
},
|
||||||
wire::{JayOutputId, JayScreencastId},
|
wire::{JayOutputId, JayScreencastId},
|
||||||
},
|
},
|
||||||
|
|
@ -120,7 +120,7 @@ impl OutputNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_preferred_scale(self: &Rc<Self>, scale: Scale) {
|
pub fn set_preferred_scale(self: &Rc<Self>, scale: Scale) {
|
||||||
let old_scale = self.global.preferred_scale.replace(scale);
|
let old_scale = self.global.persistent.scale.replace(scale);
|
||||||
if scale == old_scale {
|
if scale == old_scale {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +161,7 @@ impl OutputNode {
|
||||||
let font = self.state.theme.font.borrow_mut();
|
let font = self.state.theme.font.borrow_mut();
|
||||||
let theme = &self.state.theme;
|
let theme = &self.state.theme;
|
||||||
let th = theme.sizes.title_height.get();
|
let th = theme.sizes.title_height.get();
|
||||||
let scale = self.global.preferred_scale.get();
|
let scale = self.global.persistent.scale.get();
|
||||||
let scale = if scale != 1 {
|
let scale = if scale != 1 {
|
||||||
Some(scale.to_f64())
|
Some(scale.to_f64())
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -388,7 +388,7 @@ impl OutputNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_mode(self: &Rc<Self>, mode: Mode) {
|
pub fn update_mode(self: &Rc<Self>, mode: Mode) {
|
||||||
self.update_mode_and_transform(mode, self.global.transform.get());
|
self.update_mode_and_transform(mode, self.global.persistent.transform.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_transform(self: &Rc<Self>, transform: Transform) {
|
pub fn update_transform(self: &Rc<Self>, transform: Transform) {
|
||||||
|
|
@ -397,17 +397,13 @@ impl OutputNode {
|
||||||
|
|
||||||
pub fn update_mode_and_transform(self: &Rc<Self>, mode: Mode, transform: Transform) {
|
pub fn update_mode_and_transform(self: &Rc<Self>, mode: Mode, transform: Transform) {
|
||||||
let old_mode = self.global.mode.get();
|
let old_mode = self.global.mode.get();
|
||||||
let old_transform = self.global.transform.get();
|
let old_transform = self.global.persistent.transform.get();
|
||||||
if (old_mode, old_transform) == (mode, transform) {
|
if (old_mode, old_transform) == (mode, transform) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let (old_width, old_height) = self.global.pixel_size();
|
let (old_width, old_height) = self.global.pixel_size();
|
||||||
self.global.mode.set(mode);
|
self.global.mode.set(mode);
|
||||||
self.state
|
self.global.persistent.transform.set(transform);
|
||||||
.output_transforms
|
|
||||||
.borrow_mut()
|
|
||||||
.insert(self.global.output_id.clone(), transform);
|
|
||||||
self.global.transform.set(transform);
|
|
||||||
let (new_width, new_height) = self.global.pixel_size();
|
let (new_width, new_height) = self.global.pixel_size();
|
||||||
self.change_extents_(&self.calculate_extents());
|
self.change_extents_(&self.calculate_extents());
|
||||||
|
|
||||||
|
|
@ -436,18 +432,18 @@ impl OutputNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_extents(&self) -> Rect {
|
fn calculate_extents(&self) -> Rect {
|
||||||
let (mut width, mut height) = self.global.pixel_size();
|
let mode = self.global.mode.get();
|
||||||
let scale = self.global.preferred_scale.get();
|
let (width, height) = calculate_logical_size(
|
||||||
if scale != 1 {
|
(mode.width, mode.height),
|
||||||
let scale = scale.to_f64();
|
self.global.persistent.transform.get(),
|
||||||
width = (width as f64 / scale).round() as _;
|
self.global.persistent.scale.get(),
|
||||||
height = (height as f64 / scale).round() as _;
|
);
|
||||||
}
|
|
||||||
let pos = self.global.pos.get();
|
let pos = self.global.pos.get();
|
||||||
pos.with_size(width, height).unwrap()
|
pos.with_size(width, height).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_extents_(self: &Rc<Self>, rect: &Rect) {
|
fn change_extents_(self: &Rc<Self>, rect: &Rect) {
|
||||||
|
self.global.persistent.pos.set((rect.x1(), rect.y1()));
|
||||||
self.global.pos.set(*rect);
|
self.global.pos.set(*rect);
|
||||||
self.state.root.update_extents();
|
self.state.root.update_extents();
|
||||||
self.schedule_update_render_data();
|
self.schedule_update_render_data();
|
||||||
|
|
@ -766,3 +762,17 @@ impl Node for OutputNode {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn calculate_logical_size(
|
||||||
|
mode: (i32, i32),
|
||||||
|
transform: Transform,
|
||||||
|
scale: crate::scale::Scale,
|
||||||
|
) -> (i32, i32) {
|
||||||
|
let (mut width, mut height) = transform.maybe_swap(mode);
|
||||||
|
if scale != 1 {
|
||||||
|
let scale = scale.to_f64();
|
||||||
|
width = (width as f64 / scale).round() as _;
|
||||||
|
height = (height as f64 / scale).round() as _;
|
||||||
|
}
|
||||||
|
(width, height)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue