use std::collections::{HashMap, HashSet, VecDeque};
use std::sync::{Arc, Mutex};
use std::time::Instant;
use calloop::LoopHandle;
use halley_config::RuntimeTuning;
use halley_core::cluster::ClusterId;
use halley_core::cluster_policy::ClusterFormationState;
use halley_core::field::{Field, NodeId, Vec2};
use halley_core::viewport::Viewport;
use smithay::{
delegate_dmabuf,
desktop::PopupManager,
input::SeatState,
reexports::wayland_server::{DisplayHandle, backend::ObjectId},
wayland::{
compositor::CompositorState,
cursor_shape::CursorShapeManagerState,
dmabuf::DmabufState,
fractional_scale::FractionalScaleManagerState,
idle_notify::IdleNotifierState,
output::OutputManagerState,
pointer_constraints::PointerConstraintsState,
relative_pointer::RelativePointerManagerState,
selection::{
data_device::DataDeviceState, primary_selection::PrimarySelectionState,
wlr_data_control::DataControlState,
},
shell::wlr_layer::WlrLayerShellState,
shell::xdg::{XdgShellState, decoration::XdgDecorationState},
shm::ShmState,
viewporter::ViewporterState,
},
};
use super::carry::state::CarryState;
use super::clusters::state::ClusterState;
use super::focus::state::FocusState;
use super::fullscreen::state::FullscreenState;
use super::interaction::state::InteractionState;
use super::monitor::state::{MonitorSpace, MonitorState};
use super::platform::PlatformState;
use super::runtime::RuntimeState;
use super::spawn::state::{MonitorSpawnState, SpawnState};
use super::workspace::state::WorkspaceState;
use crate::animation::Animator;
use crate::render::state::RenderState;
pub(crate) struct ModelState {
pub(crate) carry_state: CarryState,
pub(crate) monitor_state: MonitorState,
pub(crate) focus_state: FocusState,
pub(crate) cluster_state: ClusterState,
pub(crate) workspace_state: WorkspaceState,
pub(crate) fullscreen_state: FullscreenState,
pub(crate) spawn_state: SpawnState,
pub(crate) field: Field,
pub(crate) viewport: Viewport,
pub(crate) zoom_ref_size: Vec2,
pub(crate) camera_target_center: Vec2,
pub(crate) camera_target_view_size: Vec2,
pub(crate) surface_to_node: HashMap<ObjectId, NodeId>,
pub(crate) node_app_ids: HashMap<NodeId, String>,
}
pub(crate) struct UiState {
pub(crate) render_state: RenderState,
}
pub(crate) struct InputState {
pub(crate) interaction_state: InteractionState,
}
pub struct Halley {
pub(crate) platform: PlatformState,
pub(crate) model: ModelState,
pub(crate) ui: UiState,
pub(crate) aperture: crate::aperture::ApertureState,
pub(crate) input: InputState,
pub(crate) portal: crate::protocol::wayland::portal::PortalState,
pub(crate) runtime: RuntimeState,
}
fn preferred_monitor_name(monitors: &HashMap<String, MonitorSpace>) -> Option<String> {
monitors
.iter()
.min_by(|a, b| {
let (_, am) = a;
let (_, bm) = b;
am.offset_x
.cmp(&bm.offset_x)
.then(am.offset_y.cmp(&bm.offset_y))
.then(a.0.cmp(b.0))
})
.map(|(name, _)| name.clone())
}
impl Halley {
pub(crate) const CLUSTER_OVERFLOW_REVEAL_EDGE_PX: f32 = 28.0;
pub(crate) const VIEWPORT_PAN_PRELOAD_MS: u64 = 70;
pub(crate) const VIEWPORT_PAN_DURATION_MS: u64 = 260;
pub fn new(
dh: &DisplayHandle,
loop_handle: LoopHandle<'static, Self>,
tuning: RuntimeTuning,
) -> Self {
let now = Instant::now();
let initial_aperture_config = crate::aperture::core::ApertureConfig::default();
let mut monitors = HashMap::new();
for viewport in tuning
.tty_viewports
.iter()
.filter(|viewport| viewport.enabled)
{
let width = viewport.width.max(1) as i32;
let height = viewport.height.max(1) as i32;
let global_center = Vec2 {
x: viewport.offset_x as f32 + width as f32 * 0.5,
y: viewport.offset_y as f32 + height as f32 * 0.5,
};
let view = Viewport::new(
global_center,
Vec2 {
x: width as f32,
y: height as f32,
},
);
monitors.insert(
viewport.connector.clone(),
MonitorSpace {
offset_x: viewport.offset_x,
offset_y: viewport.offset_y,
width,
height,
scale: 1.0,
viewport: view,
usable_viewport: view,
zoom_ref_size: view.size,
camera_target_center: view.center,
camera_target_view_size: view.size,
},
);
}
if monitors.is_empty() {
let view = tuning.viewport();
monitors.insert(
"default".to_string(),
MonitorSpace {
offset_x: 0,
offset_y: 0,
width: tuning.viewport_size.x.max(1.0).round() as i32,
height: tuning.viewport_size.y.max(1.0).round() as i32,
scale: 1.0,
viewport: view,
usable_viewport: view,
zoom_ref_size: tuning.viewport_size,
camera_target_center: tuning.viewport_center,
camera_target_view_size: tuning.viewport_size,
},
);
}
let current_monitor =
preferred_monitor_name(&monitors).unwrap_or_else(|| "default".to_string());
let primary_viewport = monitors
.get(¤t_monitor)
.map(|m| m.viewport)
.unwrap_or_else(|| tuning.viewport());
let primary_zoom_ref = monitors
.get(¤t_monitor)
.map(|m| m.zoom_ref_size)
.unwrap_or(tuning.viewport_size);
let mut seat_state = SeatState::new();
let seat = seat_state.new_wl_seat(dh, "halley");
let primary_selection_state = PrimarySelectionState::new::<Halley>(dh);
let data_control_state =
DataControlState::new::<Halley, _>(dh, Some(&primary_selection_state), |_| true);
let mut out = Self {
platform: PlatformState {
display_handle: dh.clone(),
compositor_state: CompositorState::new::<Halley>(dh),
viewporter_state: ViewporterState::new::<Halley>(dh),
xdg_shell_state: XdgShellState::new::<Halley>(dh),
xdg_activation_state: smithay::wayland::xdg_activation::XdgActivationState::new::<
Halley,
>(dh),
xdg_decoration_state: XdgDecorationState::new::<Halley>(dh),
cursor_shape_manager_state: CursorShapeManagerState::new::<Halley>(dh),
popup_manager: PopupManager::default(),
wlr_layer_shell_state: WlrLayerShellState::new::<Halley>(dh),
pointer_constraints_state: PointerConstraintsState::new::<Halley>(dh),
presentation_state: smithay::wayland::presentation::PresentationState::new::<Halley>(
dh,
<smithay::utils::Monotonic as smithay::utils::ClockSource>::ID as u32,
),
relative_pointer_manager_state: RelativePointerManagerState::new::<Halley>(dh),
fractional_scale_manager_state: FractionalScaleManagerState::new::<Halley>(dh),
idle_notifier_state: IdleNotifierState::new(dh, loop_handle),
drm_syncobj_state: None,
output_manager_state: OutputManagerState::new_with_xdg_output::<Halley>(dh),
shm_state: ShmState::new::<Halley>(dh, vec![]),
dmabuf_state: DmabufState::new(),
dmabuf_global: None,
seat_state,
data_device_state: DataDeviceState::new::<Halley>(dh),
primary_selection_state,
data_control_state,
session_lock: crate::protocol::wayland::session_lock::HalleySessionLockState::new::<
Halley,
_,
>(dh, |_| true),
seat,
cursor_manager: crate::render::CursorManager::default(),
dmabuf_importer: None,
dmabuf_output_feedbacks: HashMap::new(),
},
model: ModelState {
carry_state: CarryState {
carry_zone_hint: HashMap::new(),
carry_zone_last_change_ms: HashMap::new(),
carry_zone_pending: HashMap::new(),
carry_zone_pending_since_ms: HashMap::new(),
carry_activation_anim_armed: HashSet::new(),
carry_direct_nodes: HashSet::new(),
carry_state_hold: HashMap::new(),
},
monitor_state: MonitorState {
outputs: HashMap::new(),
current_monitor: current_monitor.clone(),
interaction_monitor: current_monitor.clone(),
focused_monitor: current_monitor.clone(),
monitors,
node_monitor: HashMap::new(),
layer_surface_monitor: HashMap::new(),
layer_surface_committed: HashSet::new(),
layer_surface_last_configured_size: HashMap::new(),
layer_keyboard_focus: None,
},
focus_state: FocusState {
interaction_focus_until_ms: 0,
last_surface_focus_ms: HashMap::new(),
outside_focus_ring_since_ms: HashMap::new(),
focus_trail: HashMap::new(),
blocked_monitor_focus_restore: HashSet::new(),
suppress_trail_record_once: false,
pan_restore_active_focus: None,
app_focused: true,
monitor_focus: HashMap::new(),
primary_interaction_focus: None,
focus_ring_preview_until_ms: HashMap::new(),
recent_top_node: None,
recent_top_until: None,
overlap_raise_order: HashMap::new(),
next_overlap_raise_order: 0,
},
cluster_state: ClusterState {
cluster_form_state: ClusterFormationState::default(),
cluster_names: HashMap::new(),
cluster_name_prompt: HashMap::new(),
active_cluster_workspaces: HashMap::new(),
cluster_bloom_open: HashMap::new(),
cluster_mode_selected_nodes: HashMap::new(),
workspace_hidden_nodes: HashMap::new(),
workspace_prev_viewports: HashMap::new(),
workspace_core_positions: HashMap::new(),
cluster_overflow_members: HashMap::new(),
cluster_overflow_rects: HashMap::new(),
cluster_overflow_scroll_offsets: HashMap::new(),
cluster_overflow_reveal_started_at_ms: HashMap::new(),
cluster_overflow_visible_until_ms: HashMap::new(),
cluster_overflow_promotion_anim: HashMap::new(),
cluster_slot_order: HashMap::new(),
pending_cluster_slot_transition: HashMap::new(),
},
workspace_state: WorkspaceState {
last_active_size: HashMap::new(),
manual_collapsed_nodes: HashSet::new(),
pending_manual_collapses: HashMap::new(),
pending_silent_close_until_ms: HashMap::new(),
user_pinned_nodes: HashSet::new(),
active_transitions: HashMap::new(),
primary_promote_cooldown_until_ms: HashMap::new(),
maximize_sessions: HashMap::new(),
maximize_animation: HashMap::new(),
maximize_resume: HashMap::new(),
},
fullscreen_state: FullscreenState {
fullscreen_active_node: HashMap::new(),
fullscreen_suspended_node: HashMap::new(),
fullscreen_soft_suspended_node: HashMap::new(),
fullscreen_restore: HashMap::new(),
fullscreen_motion: HashMap::new(),
fullscreen_scale_anim: HashMap::new(),
direct_scanout: HashMap::new(),
},
spawn_state: SpawnState {
pending_spawn_activate_at_ms: HashMap::new(),
pending_tiled_insert_reveal_at_ms: HashMap::new(),
pending_tiled_insert_preserve_focus: HashSet::new(),
pending_spawn_monitor: None,
per_monitor: HashMap::new(),
pending_spawn_pan_queue: VecDeque::new(),
active_spawn_pan: None,
applied_window_rules: HashMap::new(),
pending_rule_rechecks: HashSet::new(),
pending_initial_reveal: HashSet::new(),
pending_initial_spawn_placement: None,
initial_spawn_placements: HashMap::new(),
pending_pan_activate: None,
},
field: Field::new(),
viewport: primary_viewport,
zoom_ref_size: primary_zoom_ref,
camera_target_center: primary_viewport.center,
camera_target_view_size: primary_zoom_ref,
surface_to_node: HashMap::new(),
node_app_ids: HashMap::new(),
},
ui: UiState {
render_state: RenderState {
animator: Animator::new(now),
cache: Default::default(),
node_hover_mix: HashMap::new(),
node_preview_hover: HashMap::new(),
bearings_visible: false,
bearings_mix: HashMap::new(),
cluster_tile_tracks: HashMap::new(),
cluster_tile_entry_pending: HashSet::new(),
cluster_tile_frozen_geometry: HashMap::new(),
cluster_bloom_mix: HashMap::new(),
overlay_banner: HashMap::new(),
overlay_toast: HashMap::new(),
overlay_exit_confirm: HashMap::new(),
closing_window_animations: HashMap::new(),
stack_cycle_transition: HashMap::new(),
raise_animations: HashMap::new(),
landmark_slide_animations: HashMap::new(),
gpu: Default::default(),
render_last_tick: now,
},
},
aperture: crate::aperture::ApertureState::new(initial_aperture_config, now),
input: InputState {
interaction_state: InteractionState {
reset_input_state_requested: false,
pending_pointer_screen_hint: None,
last_pointer_screen_global: None,
pointer_contents: Default::default(),
pointer_surface_origin: None,
suppress_layer_shell_configure: false,
dpms_just_woke: false,
resize_active: None,
resize_static_node: None,
resize_static_lock_pos: None,
resize_static_until_ms: 0,
drag_authority_node: None,
drag_authority_velocity: Vec2 { x: 0.0, y: 0.0 },
suspend_overlap_resolve: false,
suspend_state_checks: false,
physics_velocity: HashMap::new(),
physics_last_tick: now,
smoothed_render_pos: HashMap::new(),
viewport_pan_anim: None,
pan_dominant_until_ms: 0,
active_drag: None,
cluster_join_candidate: None,
bloom_pull_preview: None,
cluster_overflow_drag_preview: None,
grabbed_layer_surface: None,
cluster_name_prompt_drag_monitor: None,
cluster_name_prompt_repeat: None,
screenshot_session: None,
pending_screenshot_capture: None,
inflight_screenshot_capture: None,
screenshot_next_serial: 1,
last_screenshot_result: None,
modal_release_keys: HashSet::new(),
pending_modal_focus_restore: None,
focus_cycle_session: None,
overlay_hover_target: None,
cursor_override_until_ms: None,
pending_core_hover: None,
pending_core_press: None,
pending_collapsed_node_press: None,
pending_move_press: None,
pending_core_click: None,
pending_collapsed_node_click: None,
grabbed_edge_pan_active: false,
grabbed_edge_pan_direction: Vec2 { x: 0.0, y: 0.0 },
grabbed_edge_pan_pressure: Vec2 { x: 0.0, y: 0.0 },
grabbed_edge_pan_monitor: None,
cursor_override_icon: None,
cursor_hidden_by_typing: false,
last_cursor_activity_at_ms: 0,
},
},
portal: crate::protocol::wayland::portal::PortalState::default(),
runtime: RuntimeState {
tuning,
surface_activity: HashMap::new(),
exit_requested: false,
started_at: now,
maintenance_dirty: true,
screenshot_full_repaint_until_ms: 0,
maintenance_ping: None,
tty_redraw_all: true,
tty_redraw_outputs: HashSet::new(),
tty_frame_callback_sequence: HashMap::new(),
pending_drm_syncobj_surfaces: Arc::new(Mutex::new(Vec::new())),
activation: Default::default(),
spawned_children: Vec::new(),
},
};
out.ui
.render_state
.animator
.set_spec(crate::animation::AnimSpec {
state_change_ms: 360,
bounce: 1.45,
});
out.model.spawn_state.per_monitor = out
.model
.monitor_state
.monitors
.iter()
.map(|(name, monitor)| {
(
name.clone(),
MonitorSpawnState::new(monitor.viewport.center),
)
})
.collect();
let current_monitor = out.model.monitor_state.current_monitor.clone();
let _ = out.load_monitor_state(current_monitor.as_str());
let _ = out.platform.display_handle.create_global::<
Halley,
smithay::reexports::wayland_protocols_wlr::screencopy::v1::server::zwlr_screencopy_manager_v1::ZwlrScreencopyManagerV1,
_,
>(3, ());
out
}
#[cfg(test)]
pub(crate) fn new_for_test(dh: &DisplayHandle, tuning: RuntimeTuning) -> Self {
let event_loop = Box::leak(Box::new(
calloop::EventLoop::<Self>::try_new().expect("test event loop"),
));
Self::new(dh, event_loop.handle(), tuning)
}
pub(crate) fn apply_aperture_config(&mut self, config: crate::aperture::core::ApertureConfig) {
self.aperture.apply_config(config);
}
pub(crate) fn node_user_pinned(&self, id: NodeId) -> bool {
self.model.workspace_state.user_pinned_nodes.contains(&id)
}
pub(crate) fn set_node_user_pinned(&mut self, id: NodeId, pinned: bool) -> bool {
if self.model.field.node(id).is_none() {
return false;
}
if pinned {
self.model.workspace_state.user_pinned_nodes.insert(id);
let _ = self.model.field.set_pinned(id, true);
} else {
self.model.workspace_state.user_pinned_nodes.remove(&id);
let _ = self
.model
.field
.set_pinned(id, self.node_session_pinned(id));
}
true
}
pub fn create_cluster(
&mut self,
members: Vec<NodeId>,
) -> Result<ClusterId, halley_core::field::ClusterCreateError> {
let members_clone = members.clone();
let cid = self.model.field.create_cluster(members)?;
for member in members_clone {
self.model.workspace_state.user_pinned_nodes.remove(&member);
}
if self
.model
.field
.cluster(cid)
.is_some_and(|cluster| cluster.pinned)
{
if let Some(core_id) = self.model.field.cluster(cid).and_then(|c| c.core) {
self.model.workspace_state.user_pinned_nodes.insert(core_id);
}
}
Ok(cid)
}
pub fn collapse_cluster(&mut self, id: ClusterId) -> Option<NodeId> {
let core_id = self.model.field.collapse_cluster(id)?;
if self
.model
.field
.cluster(id)
.is_some_and(|cluster| cluster.pinned)
{
self.model.workspace_state.user_pinned_nodes.insert(core_id);
}
Some(core_id)
}
pub(crate) fn node_session_pinned(&self, id: NodeId) -> bool {
if self
.model
.workspace_state
.maximize_sessions
.values()
.any(|session| {
session.state == crate::compositor::workspace::state::MaximizeSessionState::Active
&& session.node_snapshots.contains_key(&id)
})
{
return true;
}
let Some(entry) = self.model.fullscreen_state.fullscreen_restore.get(&id) else {
return false;
};
let node_monitor = self
.model
.monitor_state
.node_monitor
.get(&id)
.cloned()
.unwrap_or_else(|| self.model.monitor_state.current_monitor.clone());
self.model
.fullscreen_state
.fullscreen_active_node
.contains_key(&node_monitor)
|| entry.pinned
}
pub(crate) fn aperture_config(&self) -> &crate::aperture::core::ApertureConfig {
self.aperture.config()
}
pub(crate) fn aperture_snapshot_for_mode<F>(
&self,
mode: crate::aperture::core::ApertureMode,
output_rect: crate::aperture::core::Rect,
work_area_rect: crate::aperture::core::Rect,
scale: f64,
measure_text: F,
) -> Option<crate::aperture::core::ClockSnapshot>
where
F: FnMut(u32, &str) -> crate::aperture::core::Size,
{
self.aperture
.snapshot_for_mode(mode, output_rect, work_area_rect, scale, measure_text)
}
pub(crate) fn focus_ctx(&self) -> super::ctx::FocusCtx<'_> {
super::ctx::focus_ctx(self)
}
pub(crate) fn spawn_ctx(&mut self) -> super::ctx::SpawnCtx<'_> {
super::ctx::spawn_ctx(self)
}
pub(crate) fn surface_lifecycle_ctx(&mut self) -> super::ctx::SurfaceLifecycleCtx<'_> {
super::ctx::surface_lifecycle_ctx(self)
}
pub(crate) fn layer_shell_ctx(&mut self) -> super::ctx::LayerShellCtx<'_> {
super::ctx::layer_shell_ctx(self)
}
pub(crate) fn pointer_ctx(&mut self) -> super::ctx::PointerCtx<'_> {
super::ctx::pointer_ctx(self)
}
pub(crate) fn fullscreen_ctx(&mut self) -> super::ctx::FullscreenCtx<'_> {
super::ctx::fullscreen_ctx(self)
}
#[allow(dead_code)]
pub(crate) fn default_spawn_view_anchor_for_monitor(&self, monitor: &str) -> Vec2 {
super::spawn::state::default_spawn_view_anchor_for_monitor(self, monitor)
}
pub(crate) fn spawn_monitor_state(
&self,
monitor: &str,
) -> super::spawn::state::MonitorSpawnState {
super::spawn::state::spawn_monitor_state(self, monitor)
}
pub(crate) fn spawn_monitor_state_mut(
&mut self,
monitor: &str,
) -> &mut super::spawn::state::MonitorSpawnState {
super::spawn::state::spawn_monitor_state_mut(self, monitor)
}
pub(crate) fn process_pending_spawn_activations(&mut self, now: Instant, now_ms: u64) {
super::spawn::state::process_pending_spawn_activations(self, now, now_ms)
}
pub fn active_zoom_lock_scale(&self) -> f32 {
super::monitor::camera::active_zoom_lock_scale(self)
}
pub fn camera_render_scale(&self) -> f32 {
super::monitor::camera::camera_render_scale(self)
}
pub fn view_center_for_monitor(&self, monitor: &str) -> Vec2 {
super::monitor::state::view_center_for_monitor(self, monitor)
}
pub fn usable_viewport_for_monitor(&self, monitor: &str) -> Viewport {
super::monitor::state::usable_viewport_for_monitor(self, monitor)
}
pub(crate) fn load_monitor_state(&mut self, name: &str) -> bool {
super::monitor::state::load_monitor_state(self, name)
}
pub(crate) fn activate_monitor(&mut self, name: &str) -> bool {
super::monitor::state::activate_monitor(self, name)
}
pub(crate) fn begin_temporary_render_monitor(&mut self, name: &str) -> Option<String> {
super::monitor::state::begin_temporary_render_monitor(self, name)
}
pub(crate) fn end_temporary_render_monitor(&mut self, previous: Option<String>) {
super::monitor::state::end_temporary_render_monitor(self, previous)
}
pub(crate) fn interaction_monitor(&self) -> &str {
super::monitor::state::interaction_monitor(self)
}
pub(crate) fn focused_monitor(&self) -> &str {
super::monitor::state::focused_monitor(self)
}
pub(crate) fn set_interaction_monitor(&mut self, name: &str) {
super::monitor::state::set_interaction_monitor(self, name)
}
pub(crate) fn set_focused_monitor(&mut self, name: &str) {
super::monitor::state::set_focused_monitor(self, name)
}
pub(crate) fn request_input_state_reset(&mut self) {
self.input.interaction_state.reset_input_state_requested = true;
}
pub(crate) fn begin_modal_keyboard_capture(&mut self) {
self.clear_keyboard_focus();
self.request_input_state_reset();
}
pub(crate) fn schedule_modal_focus_restore(&mut self, target: Option<NodeId>, now: Instant) {
self.schedule_modal_focus_restore_after(target, now, 80);
}
pub(crate) fn schedule_modal_focus_restore_after(
&mut self,
target: Option<NodeId>,
now: Instant,
delay_ms: u64,
) {
self.input.interaction_state.pending_modal_focus_restore = Some(
crate::compositor::interaction::state::PendingModalFocusRestore {
target,
restore_at_ms: self.now_ms(now).saturating_add(delay_ms.max(1)),
},
);
self.request_input_state_reset();
self.request_maintenance();
}
pub(crate) fn reconfigure_active_tty_monitors(
&mut self,
active_viewports: &[halley_config::ViewportOutputConfig],
) {
super::monitor::state::reconfigure_active_tty_monitors(self, active_viewports)
}
pub(crate) fn monitor_for_screen(&self, sx: f32, sy: f32) -> Option<String> {
super::monitor::state::monitor_for_screen(self, sx, sy)
}
pub(crate) fn monitor_for_node_or_current(&self, node_id: NodeId) -> String {
super::monitor::state::monitor_for_node_or_current(self, node_id)
}
pub(crate) fn monitor_for_surface_or_current(
&self,
surface: &smithay::reexports::wayland_server::protocol::wl_surface::WlSurface,
) -> String {
super::monitor::state::monitor_for_surface_or_current(self, surface)
}
pub(crate) fn monitor_for_screen_or_current(&self, sx: f32, sy: f32) -> String {
super::monitor::state::monitor_for_screen_or_current(self, sx, sy)
}
pub(crate) fn monitor_for_screen_or_interaction(&self, sx: f32, sy: f32) -> String {
super::monitor::state::monitor_for_screen_or_interaction(self, sx, sy)
}
pub(crate) fn monitor_for_screen_clamped(
&self,
sx: f32,
sy: f32,
) -> Option<(String, f32, f32)> {
super::monitor::state::monitor_for_screen_clamped(self, sx, sy)
}
pub(crate) fn local_screen_in_monitor(
&self,
name: &str,
sx: f32,
sy: f32,
) -> (i32, i32, f32, f32) {
super::monitor::state::local_screen_in_monitor(self, name, sx, sy)
}
pub(crate) fn node_visible_on_current_monitor(&self, id: NodeId) -> bool {
super::monitor::state::node_visible_on_current_monitor(self, id)
}
pub(crate) fn node_assigned_to_current_monitor(&self, id: NodeId) -> bool {
super::monitor::state::node_assigned_to_current_monitor(self, id)
}
#[allow(dead_code)]
pub(crate) fn assign_node_to_current_monitor(&mut self, id: NodeId) {
let monitor = self.model.monitor_state.current_monitor.clone();
self.assign_node_to_monitor(id, monitor.as_str())
}
pub(crate) fn assign_node_to_monitor(&mut self, id: NodeId, monitor: &str) {
let previous_monitor = self.model.monitor_state.node_monitor.get(&id).cloned();
super::monitor::state::assign_node_to_monitor(self, id, monitor);
super::clusters::system::cluster_system_controller(&mut *self)
.sync_cluster_name_for_node_monitor(id, monitor);
if previous_monitor.as_deref() != Some(monitor)
&& super::workspace::state::abort_maximize_session_for_external_active_node_on_monitor(
self, monitor, id,
)
{
self.request_maintenance();
}
}
pub(crate) fn assign_layer_surface_to_monitor(
&mut self,
surface: &smithay::reexports::wayland_server::protocol::wl_surface::WlSurface,
monitor: String,
) {
super::monitor::state::assign_layer_surface_to_monitor(self, surface, monitor)
}
pub(crate) fn output_transform_for(&self, name: &str) -> smithay::utils::Transform {
super::monitor::state::output_transform_for(self, name)
}
pub(crate) fn advertise_output(&mut self, name: &str, mode: smithay::output::Mode) {
super::monitor::state::advertise_output(self, name, mode)
}
pub(crate) fn advertise_output_with_physical_size(
&mut self,
name: &str,
mode: smithay::output::Mode,
physical_size_mm: Option<(u32, u32)>,
) {
super::monitor::state::advertise_output_with_physical_size(
self,
name,
mode,
physical_size_mm,
)
}
pub(crate) fn preferred_xdg_decoration_mode(
&self,
) -> smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode{
super::platform::preferred_xdg_decoration_mode(self)
}
pub(crate) fn apply_toplevel_tiled_hint(
&self,
state: &mut smithay::wayland::shell::xdg::ToplevelState,
) {
super::platform::apply_toplevel_tiled_hint(self, state)
}
pub(crate) fn refresh_xdg_decoration_mode(&mut self) {
super::platform::refresh_xdg_decoration_mode(self)
}
pub(crate) fn effective_cursor_image_status(
&self,
) -> smithay::input::pointer::CursorImageStatus {
super::platform::effective_cursor_image_status(self)
}
pub(crate) fn install_drm_syncobj_blocker(
&mut self,
surface: &smithay::reexports::wayland_server::protocol::wl_surface::WlSurface,
) {
super::platform::install_drm_syncobj_blocker(self, surface)
}
pub(crate) fn drain_drm_syncobj_blockers(&mut self) {
super::platform::drain_drm_syncobj_blockers(self)
}
pub(crate) fn configure_dmabuf_importer(
&mut self,
importer: std::rc::Rc<dyn crate::backend::interface::DmabufImportBackend>,
main_device: Option<rustix::fs::Dev>,
) {
super::platform::configure_dmabuf_importer(self, importer, main_device)
}
pub(crate) fn configure_dmabuf_importer_for_fd<Fd: std::os::unix::io::AsFd>(
&mut self,
importer: std::rc::Rc<dyn crate::backend::interface::DmabufImportBackend>,
device_fd: Fd,
) {
super::platform::configure_dmabuf_importer_for_fd(self, importer, device_fd)
}
pub(crate) fn configure_dmabuf_output_feedbacks(
&mut self,
output_feedbacks: std::collections::HashMap<
String,
smithay::wayland::dmabuf::DmabufFeedback,
>,
) {
super::platform::configure_dmabuf_output_feedbacks(self, output_feedbacks)
}
pub fn note_input_activity(&mut self) {
super::platform::note_input_activity(self)
}
pub(crate) fn non_overlap_gap_world(&self) -> f32 {
super::overlap::system::non_overlap_gap_world(self)
}
pub(crate) fn required_sep_x(
&self,
a_pos_x: f32,
a_ext: super::overlap::system::CollisionExtents,
b_pos_x: f32,
b_ext: super::overlap::system::CollisionExtents,
gap: f32,
) -> f32 {
super::overlap::system::required_sep_x(self, a_pos_x, a_ext, b_pos_x, b_ext, gap)
}
pub(crate) fn required_sep_y(
&self,
a_pos_y: f32,
a_ext: super::overlap::system::CollisionExtents,
b_pos_y: f32,
b_ext: super::overlap::system::CollisionExtents,
gap: f32,
) -> f32 {
super::overlap::system::required_sep_y(self, a_pos_y, a_ext, b_pos_y, b_ext, gap)
}
pub(crate) fn carry_surface_non_overlap(
&mut self,
id: NodeId,
to: Vec2,
clamp_only: bool,
) -> bool {
super::overlap::system::carry_surface_non_overlap(self, id, to, clamp_only)
}
pub(crate) fn surface_window_collision_extents(
&self,
n: &halley_core::field::Node,
) -> super::overlap::system::CollisionExtents {
super::overlap::system::surface_window_collision_extents(self, n)
}
pub(crate) fn spawn_obstacle_extents_for_node(
&self,
n: &halley_core::field::Node,
) -> super::overlap::system::CollisionExtents {
super::overlap::system::spawn_obstacle_extents_for_node(self, n)
}
pub(crate) fn collision_extents_for_node(
&self,
n: &halley_core::field::Node,
) -> super::overlap::system::CollisionExtents {
super::overlap::system::collision_extents_for_node(self, n)
}
pub(crate) fn collision_size_for_node(&self, n: &halley_core::field::Node) -> Vec2 {
super::overlap::system::collision_size_for_node(self, n)
}
pub(crate) fn resolve_surface_overlap(&mut self) {
super::overlap::system::resolve_surface_overlap(self)
}
pub(crate) fn resolve_landmarks_overlapped_by_active_window(&mut self, window_id: NodeId) {
super::overlap::system::resolve_landmarks_overlapped_by_active_window(self, window_id)
}
pub(crate) fn request_toplevel_resize(&mut self, node_id: NodeId, width: i32, height: i32) {
super::overlap::system::request_toplevel_resize(self, node_id, width, height)
}
pub(crate) fn node_has_overlap_policy(&self, id: NodeId) -> bool {
super::spawn::state::node_has_overlap_policy(self, id)
}
pub(crate) fn node_draws_above_fullscreen_on_monitor(&self, id: NodeId, monitor: &str) -> bool {
super::spawn::state::node_draws_above_fullscreen_on_monitor(self, id, monitor)
}
pub(crate) fn node_draws_above_fullscreen_on_current_monitor(&self, id: NodeId) -> bool {
self.node_draws_above_fullscreen_on_monitor(
id,
self.model.monitor_state.current_monitor.as_str(),
)
}
pub(crate) fn monitor_has_visible_overlap_policy_window(&self, monitor: &str) -> bool {
super::spawn::state::monitor_has_visible_overlap_policy_window(self, monitor)
}
pub fn now_ms(&self, now: Instant) -> u64 {
super::runtime::runtime_controller(self).now_ms(now)
}
#[allow(dead_code)]
pub(crate) fn debug_dump(&self) {
super::runtime::runtime_controller(self).debug_dump()
}
pub fn apply_tuning(&mut self, tuning: RuntimeTuning) {
super::runtime::runtime_controller(self).apply_tuning(tuning)
}
pub fn request_exit(&mut self) {
super::runtime::runtime_controller(self).request_exit()
}
pub fn exit_requested(&self) -> bool {
super::runtime::runtime_controller(self).exit_requested()
}
pub fn request_maintenance(&mut self) {
super::runtime::runtime_controller(self).request_maintenance()
}
pub fn request_tty_redraw_for_monitor(&mut self, monitor: &str) {
self.runtime.tty_redraw_outputs.insert(monitor.to_string());
if let Some(ping) = &self.runtime.maintenance_ping {
ping.ping();
}
}
pub fn advance_tty_frame_callback_sequence(&mut self, output_name: &str) -> u32 {
let sequence = self
.runtime
.tty_frame_callback_sequence
.entry(output_name.to_string())
.or_insert(0);
*sequence = sequence.wrapping_add(1);
*sequence
}
pub fn tty_frame_callback_sequence(&self, output_name: &str) -> u32 {
self.runtime
.tty_frame_callback_sequence
.get(output_name)
.copied()
.unwrap_or(0)
}
#[allow(dead_code)]
pub fn next_maintenance_deadline(&self, now: Instant) -> Option<Instant> {
super::runtime::runtime_controller(self).next_maintenance_deadline(now)
}
pub fn run_maintenance_if_needed(&mut self, now: Instant) {
super::runtime::runtime_controller(self).run_maintenance_if_needed(now)
}
#[allow(dead_code)]
pub fn run_maintenance(&mut self, now: Instant) {
super::runtime::runtime_controller(self).run_maintenance(now)
}
pub(crate) fn record_focus_trail_visit(&mut self, id: NodeId) {
super::focus::trail::focus_trail_controller(self).record_focus_trail_visit(id)
}
#[cfg(test)]
pub(crate) fn trail_for_monitor_mut(
&mut self,
monitor: &str,
) -> &mut halley_core::trail::Trail {
super::focus::trail::trail_for_monitor_mut(self, monitor)
}
pub(crate) fn navigate_window_trail(
&mut self,
direction: halley_ipc::TrailDirection,
now: Instant,
) -> bool {
super::focus::trail::focus_trail_controller(self).navigate_window_trail(direction, now)
}
pub(crate) fn previous_window_from_trail_on_close(
&mut self,
monitor: &str,
closing_id: NodeId,
) -> Option<NodeId> {
super::focus::trail::focus_trail_controller(self)
.previous_window_from_trail_on_close(monitor, closing_id)
}
pub(crate) fn restore_focus_to_node_after_close(
&mut self,
monitor: &str,
id: NodeId,
now: Instant,
suppress_pan: bool,
) -> bool {
super::focus::trail::focus_trail_controller(self).restore_focus_to_node_after_close(
monitor,
id,
now,
suppress_pan,
)
}
pub(crate) fn enforce_single_primary_active_unit(&mut self) {
super::focus::decay::focus_decay_controller(self).enforce_single_primary_active_unit()
}
#[cfg(test)]
pub(crate) fn surface_is_definitively_outside_focus_ring(&self, id: NodeId) -> bool {
super::focus::decay::focus_decay_controller(self)
.surface_is_definitively_outside_focus_ring(id)
}
pub fn apply_single_surface_decay_policy(
&mut self,
id: NodeId,
now_ms: u64,
active_delay_ms: u64,
inactive_delay_ms: u64,
) {
super::focus::decay::focus_decay_controller(self).apply_single_surface_decay_policy(
id,
now_ms,
active_delay_ms,
inactive_delay_ms,
)
}
pub(crate) fn companion_surface_node(&self, now_ms: u64) -> Option<NodeId> {
super::focus::state::focus_state_controller(self).companion_surface_node(now_ms)
}
pub fn active_focus_ring(&self) -> halley_core::viewport::FocusRing {
super::focus::state::focus_state_controller(self).active_focus_ring()
}
pub fn focus_ring_for_monitor(&self, monitor: &str) -> halley_core::viewport::FocusRing {
super::focus::state::focus_state_controller(self).focus_ring_for_monitor(monitor)
}
pub fn should_draw_focus_ring_preview(&self, now: Instant) -> bool {
super::focus::state::focus_state_controller(self).should_draw_focus_ring_preview(now)
}
pub(crate) fn focus_monitor_view(&mut self, monitor: &str, now: Instant) {
super::focus::state::focus_state_controller(self).focus_monitor_view(monitor, now)
}
pub fn set_interaction_focus(&mut self, id: Option<NodeId>, hold_ms: u64, now: Instant) {
super::focus::state::focus_state_controller(self).set_interaction_focus(id, hold_ms, now)
}
pub(crate) fn restore_pan_return_active_focus(&mut self, now: Instant) {
super::focus::state::focus_state_controller(self).restore_pan_return_active_focus(now)
}
#[allow(dead_code)]
pub fn reassert_wayland_keyboard_focus_if_drifted(&mut self, id: Option<NodeId>) {
super::focus::state::focus_state_controller(self)
.reassert_wayland_keyboard_focus_if_drifted(id)
}
#[allow(dead_code)]
pub(crate) fn focused_node_for_monitor(&self, monitor: &str) -> Option<NodeId> {
super::focus::state::focus_state_controller(self).focused_node_for_monitor(monitor)
}
#[allow(dead_code)]
pub(crate) fn focused_monitor_for_node(&self, id: NodeId) -> Option<String> {
super::focus::state::focus_state_controller(self).focused_monitor_for_node(id)
}
#[allow(dead_code)]
pub(crate) fn set_monitor_focus(&mut self, monitor: &str, id: NodeId) {
super::focus::state::focus_state_controller(self).set_monitor_focus(monitor, id)
}
pub fn set_recent_top_node(&mut self, node_id: NodeId, until: Instant) {
super::focus::state::focus_state_controller(self).set_recent_top_node(node_id, until)
}
pub fn raise_overlap_policy_node(&mut self, node_id: NodeId) -> bool {
super::focus::state::focus_state_controller(self).raise_overlap_policy_node(node_id)
}
pub fn overlap_policy_stack_rank(&self, node_id: NodeId) -> (u64, u64) {
super::focus::state::focus_state_controller(self).overlap_policy_stack_rank(node_id)
}
pub(crate) fn focus_pointer_target(
&mut self,
node_id: NodeId,
hold_ms: u64,
now: Instant,
) -> NodeId {
super::focus::system::focus_pointer_target(self, node_id, hold_ms, now)
}
pub fn recent_top_node_active(&mut self, now: Instant) -> Option<NodeId> {
super::focus::state::focus_state_controller(self).recent_top_node_active(now)
}
pub(crate) fn focus_cycle_session_active(&self) -> bool {
super::focus::cycle::focus_cycle_session_active(self)
}
#[cfg(test)]
pub(crate) fn focus_cycle_preview_node(&self) -> Option<NodeId> {
super::focus::cycle::focus_cycle_preview_node(self)
}
pub(crate) fn start_or_step_focus_cycle(
&mut self,
direction: halley_config::FocusCycleBindingAction,
now: Instant,
) -> bool {
super::focus::cycle::focus_cycle_controller(self).start_or_step_focus_cycle(direction, now)
}
pub(crate) fn cancel_focus_cycle(&mut self) -> bool {
super::focus::cycle::focus_cycle_controller(self).cancel_focus_cycle()
}
pub(crate) fn commit_focus_cycle(&mut self, now: Instant) -> bool {
super::focus::cycle::focus_cycle_controller(self).commit_focus_cycle(now)
}
pub fn set_app_focused(&mut self, focused: bool) {
super::focus::system::focus_system_controller(self).set_app_focused(focused)
}
pub(crate) fn clear_keyboard_focus(&mut self) {
super::focus::system::focus_system_controller(self).clear_keyboard_focus()
}
pub fn wl_surface_for_node(
&self,
id: NodeId,
) -> Option<smithay::reexports::wayland_server::protocol::wl_surface::WlSurface> {
super::focus::system::wl_surface_for_node(self, id)
}
#[cfg(test)]
pub(crate) fn fullscreen_focus_override(&self, requested: Option<NodeId>) -> Option<NodeId> {
super::focus::system::fullscreen_focus_override(self, requested)
}
pub(crate) fn update_selection_focus_from_surface(
&self,
surface: Option<&smithay::reexports::wayland_server::protocol::wl_surface::WlSurface>,
) {
super::focus::system::update_selection_focus_from_surface(self, surface)
}
pub fn apply_wayland_focus_state(&mut self, id: Option<NodeId>) {
super::focus::system::focus_system_controller(self).apply_wayland_focus_state(id)
}
pub fn update_focus_tracking_for_surface(&mut self, fid: NodeId, now_ms: u64) {
super::focus::system::focus_system_controller(self)
.update_focus_tracking_for_surface(fid, now_ms)
}
pub fn note_pan_activity(&mut self, now: Instant) {
super::focus::system::focus_system_controller(self).note_pan_activity(now)
}
pub(crate) fn note_pan_viewport_change(&mut self, now: Instant) {
super::focus::system::focus_system_controller(self).note_pan_viewport_change(now)
}
pub fn set_pan_restore_focus_target(&mut self, id: NodeId) {
super::focus::system::focus_system_controller(self).set_pan_restore_focus_target(id)
}
pub fn animate_viewport_center_to(&mut self, target_center: Vec2, now: Instant) -> bool {
super::focus::system::focus_system_controller(self)
.animate_viewport_center_to(target_center, now)
}
pub fn animate_viewport_center_to_on_monitor(
&mut self,
monitor: &str,
target_center: Vec2,
now: Instant,
) -> bool {
super::focus::system::focus_system_controller(self).animate_viewport_center_to_on_monitor(
monitor,
target_center,
now,
)
}
pub fn animate_viewport_center_to_delayed(
&mut self,
target_center: Vec2,
now: Instant,
delay_ms: u64,
) -> bool {
super::focus::system::focus_system_controller(self).animate_viewport_center_to_delayed(
target_center,
now,
delay_ms,
)
}
pub(crate) fn tick_viewport_pan_animation(&mut self, now_ms: u64) {
super::focus::system::focus_system_controller(self).tick_viewport_pan_animation(now_ms)
}
pub(crate) fn surface_is_fully_visible_on_monitor(&self, monitor: &str, id: NodeId) -> bool {
super::focus::system::surface_is_fully_visible_on_monitor(self, monitor, id)
}
pub(crate) fn minimal_reveal_center_for_surface_on_monitor(
&self,
monitor: &str,
id: NodeId,
) -> Option<Vec2> {
super::focus::system::minimal_reveal_center_for_surface_on_monitor(self, monitor, id)
}
pub(crate) fn maybe_pan_to_restored_focus_on_close(
&mut self,
monitor: &str,
id: NodeId,
now: Instant,
) -> bool {
super::focus::system::focus_system_controller(self)
.maybe_pan_to_restored_focus_on_close(monitor, id, now)
}
pub fn begin_resize_interaction(&mut self, id: NodeId, now: Instant) {
super::focus::system::focus_system_controller(self).begin_resize_interaction(id, now)
}
pub fn end_resize_interaction(&mut self, now: Instant) {
super::focus::system::focus_system_controller(self).end_resize_interaction(now)
}
pub fn resolve_overlap_now(&mut self) {
super::focus::system::focus_system_controller(self).resolve_overlap_now()
}
pub fn set_last_active_size_now(&mut self, id: NodeId, size: Vec2) {
super::focus::system::focus_system_controller(self).set_last_active_size_now(id, size)
}
pub fn last_focused_surface_node(&self) -> Option<NodeId> {
super::focus::system::last_focused_surface_node(self)
}
pub fn last_focused_surface_node_for_monitor(&self, monitor: &str) -> Option<NodeId> {
super::focus::system::last_focused_surface_node_for_monitor(self, monitor)
}
pub fn last_input_surface_node(&self) -> Option<NodeId> {
super::focus::system::last_input_surface_node(self)
}
pub fn last_input_surface_node_for_monitor(&self, monitor: &str) -> Option<NodeId> {
super::focus::system::last_input_surface_node_for_monitor(self, monitor)
}
pub(crate) fn fullscreen_entry_scale(&self, node_id: NodeId, now_ms: u64) -> f32 {
super::fullscreen::system::fullscreen_entry_scale(self, node_id, now_ms)
}
pub(crate) fn fullscreen_monitor_for_node(&self, node_id: NodeId) -> Option<&str> {
super::fullscreen::system::fullscreen_monitor_for_node(self, node_id)
}
pub(crate) fn is_fullscreen_active(&self, node_id: NodeId) -> bool {
super::fullscreen::system::is_fullscreen_active(self, node_id)
}
pub(crate) fn is_fullscreen_session_node(&self, node_id: NodeId) -> bool {
super::fullscreen::system::is_fullscreen_session_node(self, node_id)
}
pub(crate) fn fullscreen_target_size_for(&self, monitor_name: &str) -> (i32, i32) {
self.model
.monitor_state
.outputs
.get(monitor_name)
.and_then(|output| output.current_mode())
.map(|mode| (mode.size.w, mode.size.h))
.unwrap_or_else(|| {
let space = self.model.monitor_state.monitors.get(monitor_name);
let size = space
.map(|m| m.viewport.size)
.unwrap_or(self.model.viewport.size);
(
size.x.round().max(96.0) as i32,
size.y.round().max(72.0) as i32,
)
})
}
#[cfg(test)]
pub(crate) fn soft_suspend_xdg_fullscreen(&mut self, node_id: NodeId, now: Instant) {
super::fullscreen::system::fullscreen_controller(self)
.soft_suspend_xdg_fullscreen(node_id, now)
}
pub(crate) fn enter_xdg_fullscreen(
&mut self,
node_id: NodeId,
output: Option<smithay::reexports::wayland_server::protocol::wl_output::WlOutput>,
now: Instant,
) {
super::fullscreen::system::fullscreen_controller(self)
.enter_xdg_fullscreen(node_id, output, now)
}
pub(crate) fn exit_xdg_fullscreen(&mut self, node_id: NodeId, now: Instant) {
super::fullscreen::system::fullscreen_controller(self).exit_xdg_fullscreen(node_id, now)
}
pub(crate) fn drop_fullscreen_surface(&mut self, id: NodeId, now: Instant) {
super::fullscreen::system::fullscreen_controller(self).drop_fullscreen_surface(id, now)
}
pub(crate) fn tick_fullscreen_motion(&mut self, now: Instant) {
super::fullscreen::system::fullscreen_controller(self).tick_fullscreen_motion(now)
}
#[cfg(test)]
#[allow(dead_code)]
pub(crate) fn viewport_center_for_monitor(&self, monitor: &str) -> Vec2 {
super::spawn::reveal::spawn_reveal_controller(self).viewport_center_for_monitor(monitor)
}
#[cfg(test)]
#[allow(dead_code)]
pub(crate) fn resolve_spawn_target_monitor(&self) -> String {
super::spawn::reveal::spawn_reveal_controller(self).resolve_spawn_target_monitor()
}
#[cfg(test)]
pub(crate) fn current_spawn_focus(&self, monitor: &str) -> (Option<NodeId>, Vec2) {
super::spawn::reveal::spawn_reveal_controller(self).current_spawn_focus(monitor)
}
#[cfg(test)]
#[allow(dead_code)]
pub(crate) fn viewport_fully_contains_surface_on_monitor(
&self,
monitor: &str,
id: NodeId,
) -> bool {
super::spawn::reveal::spawn_reveal_controller(self)
.viewport_fully_contains_surface_on_monitor(monitor, id)
}
#[cfg(test)]
pub(crate) fn right_spawn_candidate_for_focus(&self, id: NodeId, size: Vec2) -> Option<Vec2> {
super::spawn::reveal::spawn_reveal_controller(self)
.right_spawn_candidate_for_focus(id, size)
}
#[cfg(test)]
pub(crate) fn spawn_star_step(&self, size: Vec2) -> f32 {
super::spawn::reveal::spawn_reveal_controller(self).spawn_star_step(size)
}
#[cfg(test)]
pub(crate) fn star_candidate_offsets(&self, size: Vec2) -> Vec<Vec2> {
super::spawn::reveal::spawn_reveal_controller(self).star_candidate_offsets(size)
}
#[cfg(test)]
pub(crate) fn spawn_star_step_x(&self, size: Vec2) -> f32 {
super::spawn::reveal::spawn_reveal_controller(self).spawn_star_step_x(size)
}
#[cfg(test)]
pub(crate) fn spawn_star_step_y(&self, size: Vec2) -> f32 {
super::spawn::reveal::spawn_reveal_controller(self).spawn_star_step_y(size)
}
#[cfg(test)]
pub(crate) fn spawn_candidate_for_focus_dir(
&self,
id: NodeId,
size: Vec2,
dir: Vec2,
) -> Option<Vec2> {
super::spawn::reveal::spawn_reveal_controller(self)
.spawn_candidate_for_focus_dir(id, size, dir)
}
#[cfg(test)]
pub(crate) fn update_spawn_patch(
&mut self,
monitor: &str,
anchor: Vec2,
focus_node: Option<NodeId>,
focus_pos: Vec2,
growth_dir: Vec2,
) {
super::spawn::reveal::spawn_reveal_controller(self)
.update_spawn_patch(monitor, anchor, focus_node, focus_pos, growth_dir)
}
#[allow(dead_code)]
pub(crate) fn pick_spawn_position(&mut self, size: Vec2) -> (String, Vec2, bool) {
super::spawn::reveal::spawn_reveal_controller(self).pick_spawn_position(size)
}
pub(crate) fn spawn_target_monitor_for_intent(
&self,
intent: &super::spawn::rules::InitialWindowIntent,
) -> String {
super::spawn::reveal::spawn_reveal_controller(self).spawn_target_monitor_for_intent(intent)
}
pub(crate) fn pick_spawn_position_with_intent(
&mut self,
size: Vec2,
intent: &super::spawn::rules::InitialWindowIntent,
) -> (String, Vec2, bool) {
super::spawn::reveal::spawn_reveal_controller(self)
.pick_spawn_position_with_intent(size, intent)
}
pub(crate) fn finalize_initial_spawn_position(&mut self, id: NodeId, size: Vec2) -> bool {
super::spawn::reveal::spawn_reveal_controller(self)
.finalize_initial_spawn_position(id, size)
}
#[allow(dead_code)]
pub(crate) fn maybe_start_pending_spawn_pan(&mut self, now: Instant) {
super::spawn::reveal::spawn_reveal_controller(self).maybe_start_pending_spawn_pan(now)
}
pub(crate) fn tick_pending_spawn_pan(&mut self, now: Instant, now_ms: u64) {
super::spawn::reveal::spawn_reveal_controller(self).tick_pending_spawn_pan(now, now_ms)
}
pub(crate) fn reveal_new_toplevel_node(
&mut self,
id: NodeId,
is_transient: bool,
now: Instant,
) {
super::spawn::reveal::spawn_reveal_controller(self).reveal_new_toplevel_node(
id,
is_transient,
now,
)
}
pub(crate) fn remove_node_from_field(&mut self, id: NodeId, now_ms: u64) -> bool {
super::clusters::system::cluster_system_controller(self).remove_node_from_field(id, now_ms)
}
pub fn cluster_bloom_for_monitor(
&mut self,
monitor: &str,
) -> Option<halley_core::cluster::ClusterId> {
super::clusters::system::cluster_system_controller(self).cluster_bloom_for_monitor(monitor)
}
#[cfg(test)]
pub(crate) fn sync_cluster_monitor(
&mut self,
cid: halley_core::cluster::ClusterId,
preferred: Option<&str>,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.sync_cluster_monitor(cid, preferred)
}
#[cfg(test)]
pub(crate) fn enter_cluster_workspace_by_core(
&mut self,
core_id: NodeId,
monitor: &str,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.enter_cluster_workspace_by_core(core_id, monitor, now)
}
#[cfg(test)]
pub(crate) fn exit_cluster_workspace_for_monitor(
&mut self,
monitor: &str,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.exit_cluster_workspace_for_monitor(monitor, now)
}
pub fn open_cluster_bloom_for_monitor(
&mut self,
monitor: &str,
cid: halley_core::cluster::ClusterId,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.open_cluster_bloom_for_monitor(monitor, cid)
}
pub fn close_cluster_bloom_for_monitor(&mut self, monitor: &str) -> bool {
super::clusters::system::cluster_system_controller(self)
.close_cluster_bloom_for_monitor(monitor)
}
pub fn detach_member_from_cluster(
&mut self,
cid: halley_core::cluster::ClusterId,
member_id: NodeId,
world_pos: Vec2,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.detach_member_from_cluster(cid, member_id, world_pos, now)
}
#[allow(dead_code)]
pub fn absorb_node_into_cluster(
&mut self,
cid: halley_core::cluster::ClusterId,
node_id: NodeId,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.absorb_node_into_cluster(cid, node_id, now)
}
pub(crate) fn commit_ready_cluster_join_for_node(
&mut self,
node_id: NodeId,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.commit_ready_cluster_join_for_node(node_id, now)
}
pub fn active_cluster_workspace_for_monitor(
&self,
monitor: &str,
) -> Option<halley_core::cluster::ClusterId> {
super::clusters::system::active_cluster_workspace_for_monitor(self, monitor)
}
pub(crate) fn stack_layout_rects_for_members(
&self,
monitor: &str,
members: &[NodeId],
) -> Option<std::collections::HashMap<NodeId, halley_core::tiling::Rect>> {
super::clusters::system::stack_layout_rects_for_members(self, monitor, members)
}
pub(crate) fn reveal_cluster_overflow_for_monitor(&mut self, monitor: &str, now_ms: u64) {
super::clusters::system::cluster_system_controller(self)
.reveal_cluster_overflow_for_monitor(monitor, now_ms)
}
pub(crate) fn hide_cluster_overflow_for_monitor(&mut self, monitor: &str) {
super::clusters::system::cluster_system_controller(self)
.hide_cluster_overflow_for_monitor(monitor)
}
pub(crate) fn cluster_overflow_rect_for_monitor(
&self,
monitor: &str,
) -> Option<halley_core::tiling::Rect> {
super::clusters::system::cluster_system_controller(self)
.cluster_overflow_rect_for_monitor(monitor)
}
pub(crate) fn cluster_overflow_slot_rect_for_monitor(
&self,
monitor: &str,
overflow_len: usize,
slot_index: usize,
) -> Option<halley_core::tiling::Rect> {
super::clusters::system::cluster_system_controller(self)
.cluster_overflow_slot_rect_for_monitor(monitor, overflow_len, slot_index)
}
pub(crate) fn active_cluster_tile_rect_for_member(
&self,
monitor: &str,
member_id: NodeId,
) -> Option<halley_core::tiling::Rect> {
super::clusters::system::cluster_system_controller(self)
.active_cluster_tile_rect_for_member(monitor, member_id)
}
pub(crate) fn adjust_cluster_overflow_scroll_for_monitor(
&mut self,
monitor: &str,
delta: i32,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.adjust_cluster_overflow_scroll_for_monitor(monitor, delta)
}
pub(crate) fn cluster_spawn_rect_for_new_member(
&self,
monitor: &str,
cid: halley_core::cluster::ClusterId,
) -> Option<halley_core::tiling::Rect> {
super::clusters::system::cluster_system_controller(self)
.cluster_spawn_rect_for_new_member(monitor, cid)
}
pub fn has_any_active_cluster_workspace(&self) -> bool {
super::clusters::system::cluster_system_controller(self).has_any_active_cluster_workspace()
}
pub(crate) fn swap_cluster_overflow_member_with_visible(
&mut self,
monitor: &str,
cid: halley_core::cluster::ClusterId,
overflow_member: NodeId,
visible_member: NodeId,
now_ms: u64,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.swap_cluster_overflow_member_with_visible(
monitor,
cid,
overflow_member,
visible_member,
now_ms,
)
}
pub(crate) fn reorder_cluster_overflow_member(
&mut self,
monitor: &str,
cid: halley_core::cluster::ClusterId,
member: NodeId,
target_overflow_index: usize,
now_ms: u64,
) -> bool {
super::clusters::system::cluster_system_controller(self).reorder_cluster_overflow_member(
monitor,
cid,
member,
target_overflow_index,
now_ms,
)
}
pub(crate) fn move_active_cluster_member_to_drop_tile(
&mut self,
monitor: &str,
member: NodeId,
world_pos: Vec2,
now_ms: u64,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.move_active_cluster_member_to_drop_tile(monitor, member, world_pos, now_ms)
}
pub(crate) fn cycle_active_stack_for_monitor(
&mut self,
monitor: &str,
direction: halley_core::cluster_layout::ClusterCycleDirection,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.cycle_active_stack_for_monitor(monitor, direction, now)
}
pub fn collapse_active_cluster_workspace(&mut self, now: Instant) -> bool {
super::clusters::system::cluster_system_controller(self)
.collapse_active_cluster_workspace(now)
}
pub fn cluster_mode_active(&self) -> bool {
super::clusters::system::cluster_system_controller(self).cluster_mode_active()
}
pub fn cluster_mode_active_for_monitor(&self, monitor: &str) -> bool {
super::clusters::system::cluster_system_controller(self)
.cluster_mode_active_for_monitor(monitor)
}
pub fn enter_cluster_mode(&mut self) -> bool {
super::clusters::system::cluster_system_controller(self).enter_cluster_mode()
}
pub fn exit_cluster_mode(&mut self) -> bool {
super::clusters::system::cluster_system_controller(self).exit_cluster_mode()
}
pub fn toggle_cluster_mode_selection(&mut self, node_id: NodeId) -> bool {
super::clusters::system::cluster_system_controller(self)
.toggle_cluster_mode_selection(node_id)
}
pub fn confirm_cluster_mode(&mut self, now: Instant) -> bool {
super::clusters::system::cluster_system_controller(self).confirm_cluster_mode(now)
}
pub fn toggle_cluster_workspace_by_core(&mut self, core_id: NodeId, now: Instant) -> bool {
super::clusters::system::cluster_system_controller(self)
.toggle_cluster_workspace_by_core(core_id, now)
}
pub(crate) fn activate_cluster_slot_on_current_monitor(
&mut self,
slot: u8,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.activate_cluster_slot_on_current_monitor(slot, now)
}
pub(crate) fn process_pending_cluster_slot_transition_for_current_monitor(
&mut self,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.process_pending_cluster_slot_transition_for_current_monitor(now)
}
pub fn has_active_cluster_workspace(&self) -> bool {
super::clusters::system::cluster_system_controller(self).has_active_cluster_workspace()
}
pub(crate) fn layout_active_cluster_workspace_for_monitor(
&mut self,
monitor: &str,
now_ms: u64,
) {
super::clusters::system::cluster_system_controller(self)
.layout_active_cluster_workspace_for_monitor(monitor, now_ms)
}
pub(crate) fn focus_active_tiled_cluster_member_for_monitor(
&mut self,
monitor: &str,
preferred_index: Option<usize>,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.focus_active_tiled_cluster_member_for_monitor(monitor, preferred_index, now)
}
pub(crate) fn tile_focus_active_cluster_member_for_monitor(
&mut self,
monitor: &str,
direction: halley_config::DirectionalAction,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.tile_focus_active_cluster_member_for_monitor(monitor, direction, now)
}
pub(crate) fn tile_swap_active_cluster_member_for_monitor(
&mut self,
monitor: &str,
direction: halley_config::DirectionalAction,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.tile_swap_active_cluster_member_for_monitor(monitor, direction, now)
}
pub(crate) fn cycle_active_cluster_layout_for_monitor(
&mut self,
monitor: &str,
now: Instant,
) -> bool {
super::clusters::system::cluster_system_controller(self)
.cycle_active_cluster_layout_for_monitor(monitor, now)
}
}
impl Drop for Halley {
fn drop(&mut self) {
for child in &mut self.runtime.spawned_children {
let pgid = child.id() as i32;
if let Some(pid) = rustix::process::Pid::from_raw(pgid) {
let _ = rustix::process::kill_process_group(pid, rustix::process::Signal::TERM);
}
let _ = child.wait();
}
}
}
delegate_dmabuf!(Halley);