mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Add output disabling
Still needs an API call
This commit is contained in:
parent
a3226a3c62
commit
4b3fbd716f
9 changed files with 274 additions and 138 deletions
33
src/api.rs
33
src/api.rs
|
@ -1035,9 +1035,14 @@ impl output_service_server::OutputService for OutputService {
|
|||
if let Some(y) = y {
|
||||
loc.y = y;
|
||||
}
|
||||
state
|
||||
.pinnacle
|
||||
.change_output_state(&output, None, None, None, Some(loc));
|
||||
state.pinnacle.change_output_state(
|
||||
&mut state.backend,
|
||||
&output,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(loc),
|
||||
);
|
||||
debug!("Mapping output {} to {loc:?}", output.name());
|
||||
state.pinnacle.request_layout(&output);
|
||||
})
|
||||
|
@ -1067,7 +1072,15 @@ impl output_service_server::OutputService for OutputService {
|
|||
return;
|
||||
};
|
||||
|
||||
state.resize_output(&output, mode);
|
||||
state.pinnacle.change_output_state(
|
||||
&mut state.backend,
|
||||
&output,
|
||||
Some(mode),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
state.pinnacle.request_layout(&output);
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
@ -1102,6 +1115,7 @@ impl output_service_server::OutputService for OutputService {
|
|||
});
|
||||
|
||||
state.pinnacle.change_output_state(
|
||||
&mut state.backend,
|
||||
&output,
|
||||
None,
|
||||
None,
|
||||
|
@ -1154,9 +1168,14 @@ impl output_service_server::OutputService for OutputService {
|
|||
return;
|
||||
};
|
||||
|
||||
state
|
||||
.pinnacle
|
||||
.change_output_state(&output, None, Some(smithay_transform), None, None);
|
||||
state.pinnacle.change_output_state(
|
||||
&mut state.backend,
|
||||
&output,
|
||||
None,
|
||||
Some(smithay_transform),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
state.pinnacle.request_layout(&output);
|
||||
state.schedule_render(&output);
|
||||
})
|
||||
|
|
|
@ -151,6 +151,8 @@ pub trait BackendData: 'static {
|
|||
|
||||
// INFO: only for udev in anvil, maybe shouldn't be a trait fn?
|
||||
fn early_import(&mut self, surface: &WlSurface);
|
||||
|
||||
fn set_output_mode(&mut self, output: &Output, mode: smithay::output::Mode);
|
||||
}
|
||||
|
||||
impl BackendData for Backend {
|
||||
|
@ -180,6 +182,15 @@ impl BackendData for Backend {
|
|||
Backend::Dummy(dummy) => dummy.early_import(surface),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_output_mode(&mut self, output: &Output, mode: smithay::output::Mode) {
|
||||
match self {
|
||||
Backend::Winit(winit) => winit.set_output_mode(output, mode),
|
||||
Backend::Udev(udev) => udev.set_output_mode(output, mode),
|
||||
#[cfg(feature = "testing")]
|
||||
Backend::Dummy(dummy) => dummy.set_output_mode(output, mode),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Update surface primary scanout outputs and send frames and dmabuf feedback to visible windows
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use pinnacle_api_defs::pinnacle::signal::v0alpha1::{
|
||||
OutputConnectResponse, OutputDisconnectResponse,
|
||||
};
|
||||
use pinnacle_api_defs::pinnacle::signal::v0alpha1::OutputConnectResponse;
|
||||
use smithay::backend::renderer::test::DummyRenderer;
|
||||
use smithay::backend::renderer::ImportMemWl;
|
||||
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
||||
|
@ -50,6 +48,10 @@ impl BackendData for Dummy {
|
|||
fn reset_buffers(&mut self, _output: &Output) {}
|
||||
|
||||
fn early_import(&mut self, _surface: &WlSurface) {}
|
||||
|
||||
fn set_output_mode(&mut self, _output: &Output, _mode: smithay::output::Mode) {
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
|
||||
impl Dummy {
|
||||
|
@ -141,14 +143,4 @@ impl Pinnacle {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub fn remove_output(&mut self, output: &Output) {
|
||||
self.space.unmap_output(output);
|
||||
|
||||
self.signal_state.output_disconnect.signal(|buffer| {
|
||||
buffer.push_back(OutputDisconnectResponse {
|
||||
output_name: Some(output.name()),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,6 @@ use smithay::{
|
|||
presentation_time::server::wp_presentation_feedback,
|
||||
},
|
||||
wayland_server::{
|
||||
backend::GlobalId,
|
||||
protocol::{wl_shm, wl_surface::WlSurface},
|
||||
DisplayHandle,
|
||||
},
|
||||
|
@ -527,9 +526,12 @@ impl Udev {
|
|||
/// Schedule a new render that will cause the compositor to redraw everything.
|
||||
pub fn schedule_render(&mut self, loop_handle: &LoopHandle<State>, output: &Output) {
|
||||
let Some(surface) = render_surface_for_output(output, &mut self.backends) else {
|
||||
tracing::info!("no render surface on output {}", output.name());
|
||||
return;
|
||||
};
|
||||
|
||||
// tracing::info!(state = ?surface.render_state, name = output.name());
|
||||
|
||||
match &surface.render_state {
|
||||
RenderState::Idle => {
|
||||
let output = output.clone();
|
||||
|
@ -577,6 +579,12 @@ impl Udev {
|
|||
{
|
||||
warn!("Failed to reset compositor state on crtc {crtc:?}: {err}");
|
||||
}
|
||||
|
||||
if let Some(surface) = render_surface_for_output(output, &mut self.backends) {
|
||||
if let RenderState::Scheduled(idle) = std::mem::take(&mut surface.render_state) {
|
||||
idle.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -638,51 +646,6 @@ impl State {
|
|||
// );
|
||||
}
|
||||
}
|
||||
|
||||
/// Resize the output with the given mode.
|
||||
///
|
||||
/// TODO: This is in udev.rs but is also used in winit.rs.
|
||||
/// | I've got no clue how to make things public without making a mess.
|
||||
pub fn resize_output(&mut self, output: &Output, mode: smithay::output::Mode) {
|
||||
if let Backend::Udev(udev) = &mut self.backend {
|
||||
let drm_mode = udev.backends.iter().find_map(|(_, backend)| {
|
||||
backend
|
||||
.drm_scanner
|
||||
.crtcs()
|
||||
.find(|(_, handle)| {
|
||||
output
|
||||
.user_data()
|
||||
.get::<UdevOutputData>()
|
||||
.is_some_and(|data| &data.crtc == handle)
|
||||
})
|
||||
.and_then(|(info, _)| {
|
||||
info.modes()
|
||||
.iter()
|
||||
.find(|m| smithay::output::Mode::from(**m) == mode)
|
||||
})
|
||||
.copied()
|
||||
});
|
||||
|
||||
if let Some(drm_mode) = drm_mode {
|
||||
if let Some(render_surface) = render_surface_for_output(output, &mut udev.backends)
|
||||
{
|
||||
match render_surface.compositor.use_mode(drm_mode) {
|
||||
Ok(()) => {
|
||||
self.pinnacle
|
||||
.change_output_state(output, Some(mode), None, None, None);
|
||||
}
|
||||
Err(err) => error!("Failed to resize output: {err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.pinnacle
|
||||
.change_output_state(output, Some(mode), None, None, None);
|
||||
}
|
||||
|
||||
self.pinnacle.request_layout(output);
|
||||
self.schedule_render(output);
|
||||
}
|
||||
}
|
||||
|
||||
impl BackendData for Udev {
|
||||
|
@ -705,6 +668,45 @@ impl BackendData for Udev {
|
|||
warn!("early buffer import failed: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_output_mode(&mut self, output: &Output, mode: smithay::output::Mode) {
|
||||
let drm_mode = self.backends.iter().find_map(|(_, backend)| {
|
||||
backend
|
||||
.drm_scanner
|
||||
.crtcs()
|
||||
.find(|(_, handle)| {
|
||||
output
|
||||
.user_data()
|
||||
.get::<UdevOutputData>()
|
||||
.is_some_and(|data| &data.crtc == handle)
|
||||
})
|
||||
.and_then(|(info, _)| {
|
||||
info.modes()
|
||||
.iter()
|
||||
.find(|m| smithay::output::Mode::from(**m) == mode)
|
||||
})
|
||||
.copied()
|
||||
});
|
||||
|
||||
if let Some(drm_mode) = drm_mode {
|
||||
if let Some(render_surface) = render_surface_for_output(output, &mut self.backends) {
|
||||
match render_surface.compositor.use_mode(drm_mode) {
|
||||
Ok(()) => {
|
||||
output.change_current_state(Some(mode), None, None, None);
|
||||
output.with_state_mut(|state| {
|
||||
if !state.modes.contains(&mode) {
|
||||
state.modes.push(mode);
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(err) => warn!("Failed to resize output: {err}"),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: create new drm mode with cvt
|
||||
tracing::info!("no drm mode for mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: document desperately
|
||||
|
@ -810,7 +812,6 @@ enum RenderState {
|
|||
/// The idle token from a render being scheduled.
|
||||
/// This is used to cancel renders if, for example,
|
||||
/// the output being rendered is removed.
|
||||
#[allow(dead_code)] // TODO:
|
||||
Idle<'static>,
|
||||
),
|
||||
/// A frame was rendered and scheduled and we are waiting for vblank.
|
||||
|
@ -823,10 +824,6 @@ enum RenderState {
|
|||
|
||||
/// Render surface for an output.
|
||||
struct RenderSurface {
|
||||
/// The output global id.
|
||||
global: Option<GlobalId>,
|
||||
/// A display handle used to remove the global on drop.
|
||||
display_handle: DisplayHandle,
|
||||
/// The node from `connector_connected`.
|
||||
device_id: DrmNode,
|
||||
/// The node rendering to the screen? idk
|
||||
|
@ -862,15 +859,6 @@ struct ScreencopyCommitState {
|
|||
_cursor: CommitCounter,
|
||||
}
|
||||
|
||||
impl Drop for RenderSurface {
|
||||
// Stop advertising this output to clients on drop.
|
||||
fn drop(&mut self) {
|
||||
if let Some(global) = self.global.take() {
|
||||
self.display_handle.remove_global::<State>(global);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type GbmDrmCompositor = DrmCompositor<
|
||||
GbmAllocator<DrmDeviceFd>,
|
||||
GbmDevice<DrmDeviceFd>,
|
||||
|
@ -1055,11 +1043,12 @@ impl Udev {
|
|||
);
|
||||
let global = output.create_global::<State>(&self.display_handle);
|
||||
|
||||
pinnacle
|
||||
.output_management_manager_state
|
||||
.add_head::<State>(&output);
|
||||
pinnacle.outputs.insert(output.clone(), global);
|
||||
|
||||
output.with_state_mut(|state| state.serial = serial);
|
||||
output.with_state_mut(|state| {
|
||||
state.serial = serial;
|
||||
state.powered = true;
|
||||
});
|
||||
|
||||
output.set_preferred(wl_mode);
|
||||
|
||||
|
@ -1071,6 +1060,10 @@ impl Udev {
|
|||
.collect::<Vec<_>>();
|
||||
output.with_state_mut(|state| state.modes = modes);
|
||||
|
||||
pinnacle
|
||||
.output_management_manager_state
|
||||
.add_head::<State>(&output);
|
||||
|
||||
let x = pinnacle.space.outputs().fold(0, |acc, o| {
|
||||
let Some(geo) = pinnacle.space.output_geometry(o) else {
|
||||
unreachable!()
|
||||
|
@ -1131,10 +1124,8 @@ impl Udev {
|
|||
);
|
||||
|
||||
let surface = RenderSurface {
|
||||
display_handle: self.display_handle.clone(),
|
||||
device_id: node,
|
||||
render_node: device.render_node,
|
||||
global: Some(global),
|
||||
compositor,
|
||||
dmabuf_feedback,
|
||||
render_state: RenderState::Idle,
|
||||
|
@ -1145,7 +1136,7 @@ impl Udev {
|
|||
|
||||
device.surfaces.insert(crtc, surface);
|
||||
|
||||
pinnacle.change_output_state(&output, Some(wl_mode), None, None, Some(position));
|
||||
pinnacle.change_output_state(self, &output, Some(wl_mode), None, None, Some(position));
|
||||
|
||||
// If there is saved connector state, the connector was previously plugged in.
|
||||
// In this case, restore its tags and location.
|
||||
|
@ -1157,7 +1148,7 @@ impl Udev {
|
|||
{
|
||||
let ConnectorSavedState { loc, tags, scale } = saved_state;
|
||||
output.with_state_mut(|state| state.tags.clone_from(tags));
|
||||
pinnacle.change_output_state(&output, None, None, *scale, Some(*loc));
|
||||
pinnacle.change_output_state(self, &output, None, None, *scale, Some(*loc));
|
||||
} else {
|
||||
pinnacle.signal_state.output_connect.signal(|buffer| {
|
||||
buffer.push_back(OutputConnectResponse {
|
||||
|
@ -1223,6 +1214,11 @@ impl Udev {
|
|||
pinnacle
|
||||
.output_management_manager_state
|
||||
.remove_head(&output);
|
||||
|
||||
if let Some(global) = pinnacle.outputs.remove(&output) {
|
||||
// TODO: disable ahead of time
|
||||
pinnacle.display_handle.remove_global::<State>(global);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1298,11 +1294,15 @@ impl Udev {
|
|||
return;
|
||||
};
|
||||
|
||||
let output = if let Some(output) = pinnacle.space.outputs().find(|o| {
|
||||
let udev_op_data = o.user_data().get::<UdevOutputData>();
|
||||
udev_op_data
|
||||
.is_some_and(|data| data.device_id == surface.device_id && data.crtc == crtc)
|
||||
}) {
|
||||
let output = if let Some(output) = pinnacle
|
||||
.outputs
|
||||
.keys()
|
||||
.chain(pinnacle.unmapped_outputs.iter())
|
||||
.find(|o| {
|
||||
let udev_op_data = o.user_data().get::<UdevOutputData>();
|
||||
udev_op_data
|
||||
.is_some_and(|data| data.device_id == surface.device_id && data.crtc == crtc)
|
||||
}) {
|
||||
output.clone()
|
||||
} else {
|
||||
// somehow we got called with an invalid output
|
||||
|
@ -1394,6 +1394,11 @@ impl Udev {
|
|||
|
||||
assert!(matches!(surface.render_state, RenderState::Scheduled(_)));
|
||||
|
||||
if !pinnacle.outputs.contains_key(output) {
|
||||
surface.render_state = RenderState::Idle;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: possibly lift this out and make it so that scheduling a render
|
||||
// does nothing on powered off outputs
|
||||
if output.with_state(|state| !state.powered) {
|
||||
|
|
|
@ -67,6 +67,10 @@ impl BackendData for Winit {
|
|||
}
|
||||
|
||||
fn early_import(&mut self, _surface: &WlSurface) {}
|
||||
|
||||
fn set_output_mode(&mut self, output: &Output, mode: smithay::output::Mode) {
|
||||
output.change_current_state(Some(mode), None, None, None);
|
||||
}
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
|
@ -201,6 +205,7 @@ impl Winit {
|
|||
refresh: 144_000,
|
||||
};
|
||||
state.pinnacle.change_output_state(
|
||||
&mut state.backend,
|
||||
&output,
|
||||
Some(mode),
|
||||
None,
|
||||
|
|
|
@ -22,7 +22,7 @@ use smithay::{
|
|||
pointer::{CursorImageStatus, PointerHandle},
|
||||
Seat, SeatHandler, SeatState,
|
||||
},
|
||||
output::{Output, Scale},
|
||||
output::{Mode, Output, Scale},
|
||||
reexports::{
|
||||
calloop::Interest,
|
||||
wayland_protocols::xdg::shell::server::xdg_positioner::ConstraintAdjustment,
|
||||
|
@ -930,21 +930,55 @@ impl OutputManagementHandler for State {
|
|||
fn apply_configuration(&mut self, config: HashMap<Output, OutputConfiguration>) -> bool {
|
||||
for (output, config) in config {
|
||||
match config {
|
||||
OutputConfiguration::Disabled => todo!(),
|
||||
OutputConfiguration::Disabled => {
|
||||
self.pinnacle.set_output_enabled(&output, false);
|
||||
// TODO: split
|
||||
self.backend.set_output_powered(&output, false);
|
||||
}
|
||||
OutputConfiguration::Enabled {
|
||||
mode,
|
||||
position,
|
||||
transform,
|
||||
scale,
|
||||
adaptive_sync,
|
||||
adaptive_sync: _,
|
||||
} => {
|
||||
self.pinnacle.set_output_enabled(&output, true);
|
||||
// TODO: split
|
||||
self.backend.set_output_powered(&output, true);
|
||||
|
||||
self.schedule_render(&output);
|
||||
|
||||
let snapshots = self.backend.with_renderer(|renderer| {
|
||||
capture_snapshots_on_output(&mut self.pinnacle, renderer, &output, [])
|
||||
});
|
||||
|
||||
let mode = mode.map(|(size, refresh)| {
|
||||
if let Some(refresh) = refresh {
|
||||
Mode {
|
||||
size,
|
||||
refresh: refresh.get() as i32,
|
||||
}
|
||||
} else {
|
||||
output
|
||||
.with_state(|state| {
|
||||
state
|
||||
.modes
|
||||
.iter()
|
||||
.filter(|mode| mode.size == size)
|
||||
.max_by_key(|mode| mode.refresh)
|
||||
.copied()
|
||||
})
|
||||
.unwrap_or(Mode {
|
||||
size,
|
||||
refresh: 60_000,
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
self.pinnacle.change_output_state(
|
||||
&mut self.backend,
|
||||
&output,
|
||||
None,
|
||||
mode,
|
||||
transform,
|
||||
scale.map(Scale::Fractional),
|
||||
position,
|
||||
|
|
113
src/output.rs
113
src/output.rs
|
@ -2,7 +2,9 @@
|
|||
|
||||
use std::{cell::RefCell, num::NonZeroU32};
|
||||
|
||||
use pinnacle_api_defs::pinnacle::signal::v0alpha1::{OutputMoveResponse, OutputResizeResponse};
|
||||
use pinnacle_api_defs::pinnacle::signal::v0alpha1::{
|
||||
OutputDisconnectResponse, OutputMoveResponse, OutputResizeResponse,
|
||||
};
|
||||
use smithay::{
|
||||
desktop::layer_map_for_output,
|
||||
output::{Mode, Output, Scale},
|
||||
|
@ -12,6 +14,8 @@ use smithay::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
backend::BackendData,
|
||||
config::ConnectorSavedState,
|
||||
focus::WindowKeyboardFocusStack,
|
||||
layout::transaction::{LayoutTransaction, SnapshotTarget},
|
||||
protocol::screencopy::Screencopy,
|
||||
|
@ -51,7 +55,7 @@ pub enum BlankingState {
|
|||
}
|
||||
|
||||
/// The state of an output
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct OutputState {
|
||||
pub tags: Vec<Tag>,
|
||||
pub focus_stack: WindowKeyboardFocusStack,
|
||||
|
@ -69,22 +73,6 @@ pub struct OutputState {
|
|||
pub powered: bool,
|
||||
}
|
||||
|
||||
impl Default for OutputState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
tags: Default::default(),
|
||||
focus_stack: Default::default(),
|
||||
screencopy: Default::default(),
|
||||
serial: Default::default(),
|
||||
modes: Default::default(),
|
||||
lock_surface: Default::default(),
|
||||
blanking_state: Default::default(),
|
||||
layout_transaction: Default::default(),
|
||||
powered: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WithState for Output {
|
||||
type State = OutputState;
|
||||
|
||||
|
@ -135,10 +123,9 @@ impl OutputState {
|
|||
}
|
||||
|
||||
impl Pinnacle {
|
||||
/// A wrapper around [`Output::change_current_state`] that additionally sends an output
|
||||
/// geometry signal.
|
||||
pub fn change_output_state(
|
||||
&mut self,
|
||||
backend: &mut impl BackendData,
|
||||
output: &Output,
|
||||
mode: Option<Mode>,
|
||||
transform: Option<Transform>,
|
||||
|
@ -147,7 +134,7 @@ impl Pinnacle {
|
|||
) {
|
||||
let old_scale = output.current_scale().fractional_scale();
|
||||
|
||||
output.change_current_state(mode, transform, scale, location);
|
||||
output.change_current_state(None, transform, scale, location);
|
||||
if let Some(location) = location {
|
||||
self.space.map_output(output, location);
|
||||
self.signal_state.output_move.signal(|buf| {
|
||||
|
@ -158,6 +145,11 @@ impl Pinnacle {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(mode) = mode {
|
||||
backend.set_output_mode(output, mode);
|
||||
}
|
||||
|
||||
if mode.is_some() || transform.is_some() || scale.is_some() {
|
||||
layer_map_for_output(output).arrange();
|
||||
self.signal_state.output_resize.signal(|buf| {
|
||||
|
@ -169,10 +161,6 @@ impl Pinnacle {
|
|||
});
|
||||
});
|
||||
}
|
||||
if let Some(mode) = mode {
|
||||
output.set_preferred(mode);
|
||||
output.with_state_mut(|state| state.modes.push(mode));
|
||||
}
|
||||
|
||||
if let Some(scale) = scale {
|
||||
let pos_multiplier = old_scale / scale.fractional_scale();
|
||||
|
@ -223,4 +211,79 @@ impl Pinnacle {
|
|||
self.output_management_manager_state
|
||||
.update_head::<State>(output);
|
||||
}
|
||||
|
||||
pub fn set_output_enabled(&mut self, output: &Output, enabled: bool) {
|
||||
if enabled {
|
||||
self.unmapped_outputs.remove(output);
|
||||
if !self.outputs.contains_key(output) {
|
||||
let global = output.create_global::<State>(&self.display_handle);
|
||||
self.outputs.insert(output.clone(), global);
|
||||
}
|
||||
self.space.map_output(output, output.current_location());
|
||||
|
||||
// TODO: output connect?
|
||||
} else {
|
||||
let global = self.outputs.remove(output);
|
||||
if let Some(global) = global {
|
||||
self.display_handle.remove_global::<State>(global);
|
||||
}
|
||||
self.space.unmap_output(output);
|
||||
self.unmapped_outputs.insert(output.clone());
|
||||
|
||||
// TODO: should this trigger the signal?
|
||||
self.signal_state.output_disconnect.signal(|buffer| {
|
||||
buffer.push_back(OutputDisconnectResponse {
|
||||
output_name: Some(output.name()),
|
||||
})
|
||||
});
|
||||
|
||||
self.gamma_control_manager_state.output_removed(output);
|
||||
|
||||
self.config.connector_saved_states.insert(
|
||||
OutputName(output.name()),
|
||||
ConnectorSavedState {
|
||||
loc: output.current_location(),
|
||||
tags: output.with_state(|state| state.tags.clone()),
|
||||
scale: Some(output.current_scale()),
|
||||
},
|
||||
);
|
||||
|
||||
for layer in layer_map_for_output(output).layers() {
|
||||
layer.layer_surface().send_close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_output(&mut self, output: &Output) {
|
||||
let global = self.outputs.remove(output);
|
||||
if let Some(global) = global {
|
||||
self.display_handle.remove_global::<State>(global);
|
||||
}
|
||||
self.unmapped_outputs.remove(output);
|
||||
|
||||
self.space.unmap_output(output);
|
||||
|
||||
self.gamma_control_manager_state.output_removed(output);
|
||||
|
||||
self.output_management_manager_state.remove_head(output);
|
||||
|
||||
self.signal_state.output_disconnect.signal(|buffer| {
|
||||
buffer.push_back(OutputDisconnectResponse {
|
||||
output_name: Some(output.name()),
|
||||
})
|
||||
});
|
||||
|
||||
self.config.connector_saved_states.insert(
|
||||
OutputName(output.name()),
|
||||
ConnectorSavedState {
|
||||
loc: output.current_location(),
|
||||
tags: output.with_state(|state| state.tags.clone()),
|
||||
scale: Some(output.current_scale()),
|
||||
},
|
||||
);
|
||||
|
||||
for layer in layer_map_for_output(output).layers() {
|
||||
layer.layer_surface().send_close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ pub struct OutputData {
|
|||
position: Point<i32, Logical>,
|
||||
transform: Transform,
|
||||
scale: f64,
|
||||
adaptive_sync: bool,
|
||||
_adaptive_sync: bool,
|
||||
}
|
||||
|
||||
impl OutputManagementManagerState {
|
||||
|
@ -127,7 +127,7 @@ impl OutputManagementManagerState {
|
|||
position: output.current_location(),
|
||||
transform: output.current_transform(),
|
||||
scale: output.current_scale().fractional_scale(),
|
||||
adaptive_sync: false, // TODO:
|
||||
_adaptive_sync: false, // TODO:
|
||||
};
|
||||
|
||||
self.outputs.insert(output.clone(), output_data);
|
||||
|
@ -336,7 +336,7 @@ where
|
|||
head.physical_size(physical_props.size.w, physical_props.size.h);
|
||||
|
||||
let mut wlr_modes = Vec::new();
|
||||
for mode in output.modes() {
|
||||
for mode in output.with_state(|state| state.modes.clone()) {
|
||||
let wlr_mode = client
|
||||
.create_resource::<ZwlrOutputModeV1, _, D>(display, manager.version(), mode)
|
||||
.unwrap();
|
||||
|
@ -551,13 +551,13 @@ where
|
|||
|
||||
impl<D> Dispatch<ZwlrOutputHeadV1, Output, D> for OutputManagementManagerState {
|
||||
fn request(
|
||||
state: &mut D,
|
||||
client: &Client,
|
||||
resource: &ZwlrOutputHeadV1,
|
||||
_state: &mut D,
|
||||
_client: &Client,
|
||||
_resource: &ZwlrOutputHeadV1,
|
||||
request: <ZwlrOutputHeadV1 as Resource>::Request,
|
||||
data: &Output,
|
||||
dhandle: &DisplayHandle,
|
||||
data_init: &mut DataInit<'_, D>,
|
||||
_data: &Output,
|
||||
_dhandle: &DisplayHandle,
|
||||
_data_init: &mut DataInit<'_, D>,
|
||||
) {
|
||||
match request {
|
||||
zwlr_output_head_v1::Request::Release => {
|
||||
|
@ -570,13 +570,13 @@ impl<D> Dispatch<ZwlrOutputHeadV1, Output, D> for OutputManagementManagerState {
|
|||
|
||||
impl<D> Dispatch<ZwlrOutputModeV1, Mode, D> for OutputManagementManagerState {
|
||||
fn request(
|
||||
state: &mut D,
|
||||
client: &Client,
|
||||
resource: &ZwlrOutputModeV1,
|
||||
_state: &mut D,
|
||||
_client: &Client,
|
||||
_resource: &ZwlrOutputModeV1,
|
||||
request: <ZwlrOutputModeV1 as Resource>::Request,
|
||||
data: &Mode,
|
||||
dhandle: &DisplayHandle,
|
||||
data_init: &mut DataInit<'_, D>,
|
||||
_data: &Mode,
|
||||
_dhandle: &DisplayHandle,
|
||||
_data_init: &mut DataInit<'_, D>,
|
||||
) {
|
||||
match request {
|
||||
zwlr_output_mode_v1::Request::Release => {
|
||||
|
|
|
@ -22,10 +22,11 @@ use pinnacle_api_defs::pinnacle::v0alpha1::ShutdownWatchResponse;
|
|||
use smithay::{
|
||||
desktop::{PopupManager, Space},
|
||||
input::{keyboard::XkbConfig, pointer::CursorImageStatus, Seat, SeatState},
|
||||
output::Output,
|
||||
reexports::{
|
||||
calloop::{generic::Generic, Interest, LoopHandle, LoopSignal, Mode, PostAction},
|
||||
wayland_server::{
|
||||
backend::{ClientData, ClientId, DisconnectReason},
|
||||
backend::{ClientData, ClientId, DisconnectReason, GlobalId},
|
||||
protocol::wl_surface::WlSurface,
|
||||
Client, Display, DisplayHandle,
|
||||
},
|
||||
|
@ -149,6 +150,9 @@ pub struct Pinnacle {
|
|||
|
||||
/// WlSurfaces with an attached idle inhibitor.
|
||||
pub idle_inhibiting_surfaces: HashSet<WlSurface>,
|
||||
|
||||
pub outputs: HashMap<Output, GlobalId>,
|
||||
pub unmapped_outputs: HashSet<Output>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
@ -343,6 +347,9 @@ impl Pinnacle {
|
|||
root_surface_cache: HashMap::new(),
|
||||
|
||||
idle_inhibiting_surfaces: HashSet::new(),
|
||||
|
||||
outputs: HashMap::new(),
|
||||
unmapped_outputs: HashSet::new(),
|
||||
};
|
||||
|
||||
Ok(pinnacle)
|
||||
|
|
Loading…
Reference in a new issue