use std::collections::HashMap;
use std::os::unix::io::AsRawFd;
use std::process::Command;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::{env, thread};
use anyhow::Context;
use directories::UserDirs;
use sd_notify::NotifyState;
use smithay::backend::allocator::Fourcc;
use smithay::backend::renderer::element::surface::{
render_elements_from_surface_tree, WaylandSurfaceRenderElement,
};
use smithay::backend::renderer::element::texture::{TextureBuffer, TextureRenderElement};
use smithay::backend::renderer::element::{
render_elements, AsRenderElements, Element, RenderElement, RenderElementStates,
};
use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture};
use smithay::backend::renderer::{Bind, ExportMem, Frame, ImportAll, Offscreen, Renderer};
use smithay::desktop::utils::{
send_dmabuf_feedback_surface_tree, send_frames_surface_tree,
surface_presentation_feedback_flags_from_states, take_presentation_feedback_surface_tree,
OutputPresentationFeedback,
};
use smithay::desktop::{
layer_map_for_output, LayerSurface, PopupManager, Space, Window, WindowSurfaceType,
};
use smithay::input::keyboard::XkbConfig;
use smithay::input::pointer::{CursorImageAttributes, CursorImageStatus, MotionEvent};
use smithay::input::{Seat, SeatState};
use smithay::output::Output;
use smithay::reexports::calloop::generic::Generic;
use smithay::reexports::calloop::{Idle, Interest, LoopHandle, LoopSignal, Mode, PostAction};
use smithay::reexports::nix::libc::CLOCK_MONOTONIC;
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::WmCapabilities;
use smithay::reexports::wayland_server::backend::{
ClientData, ClientId, DisconnectReason, GlobalId,
};
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::reexports::wayland_server::{Display, DisplayHandle};
use smithay::utils::{
IsAlive, Logical, Physical, Point, Rectangle, Scale, Transform, SERIAL_COUNTER,
};
use smithay::wayland::compositor::{with_states, CompositorClientState, CompositorState};
use smithay::wayland::data_device::DataDeviceState;
use smithay::wayland::dmabuf::DmabufFeedback;
use smithay::wayland::output::OutputManagerState;
use smithay::wayland::pointer_gestures::PointerGesturesState;
use smithay::wayland::presentation::PresentationState;
use smithay::wayland::shell::wlr_layer::{Layer, WlrLayerShellState};
use smithay::wayland::shell::xdg::XdgShellState;
use smithay::wayland::shm::ShmState;
use smithay::wayland::socket::ListeningSocketSource;
use smithay::wayland::tablet_manager::TabletManagerState;
use time::OffsetDateTime;
use crate::backend::{Backend, Tty, Winit};
use crate::config::Config;
use crate::dbus::mutter_service_channel::ServiceChannel;
use crate::frame_clock::FrameClock;
use crate::layout::{MonitorRenderElement, MonitorSet};
use crate::utils::{center, get_monotonic_time, load_default_cursor};
use crate::LoopData;
pub struct Niri {
pub event_loop: LoopHandle<'static, LoopData>,
pub stop_signal: LoopSignal,
pub display_handle: DisplayHandle,
// Each workspace corresponds to a Space. Each workspace generally has one Output mapped to it,
// however it may have none (when there are no outputs connected) or mutiple (when mirroring).
pub monitor_set: MonitorSet<Window>,
// This space does not actually contain any windows, but all outputs are mapped into it
// according to their global position.
pub global_space: Space<Window>,
// Windows which don't have a buffer attached yet.
pub unmapped_windows: HashMap<WlSurface, Window>,
pub output_state: HashMap<Output, OutputState>,
// Smithay state.
pub compositor_state: CompositorState,
pub xdg_shell_state: XdgShellState,
pub layer_shell_state: WlrLayerShellState,
pub shm_state: ShmState,
pub output_manager_state: OutputManagerState,
pub seat_state: SeatState<State>,
pub tablet_state: TabletManagerState,
pub pointer_gestures_state: PointerGesturesState,
pub data_device_state: DataDeviceState,
pub popups: PopupManager,
pub presentation_state: PresentationState,
pub seat: Seat<State>,
pub pointer_buffer: Option<(TextureBuffer<GlesTexture>, Point<i32, Physical>)>,
pub cursor_image: CursorImageStatus,
pub dnd_icon: Option<WlSurface>,
pub zbus_conn: Option<zbus::blocking::Connection>,
pub inhibit_power_key_fd: Option<zbus::zvariant::OwnedFd>,
}
pub struct OutputState {
pub global: GlobalId,
// Set if there's a redraw queued on the event loop. Reset in redraw() which means that you
// cannot queue