mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Move all traits one layer up
This commit is contained in:
+38
-9
@@ -1,6 +1,7 @@
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::output::Output;
|
||||
|
||||
use crate::input::CompositorMod;
|
||||
use crate::niri::OutputRenderElements;
|
||||
use crate::Niri;
|
||||
|
||||
@@ -49,19 +50,47 @@ impl Backend {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tty(&mut self) -> Option<&mut Tty> {
|
||||
if let Self::Tty(v) = self {
|
||||
Some(v)
|
||||
} else {
|
||||
None
|
||||
pub fn mod_key(&self) -> CompositorMod {
|
||||
match self {
|
||||
Backend::Tty(_) => CompositorMod::Super,
|
||||
Backend::Winit(_) => CompositorMod::Alt,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn winit(&mut self) -> Option<&mut Winit> {
|
||||
if let Self::Winit(v) = self {
|
||||
Some(v)
|
||||
pub fn change_vt(&mut self, vt: i32) {
|
||||
match self {
|
||||
Backend::Tty(tty) => tty.change_vt(vt),
|
||||
Backend::Winit(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn suspend(&mut self) {
|
||||
match self {
|
||||
Backend::Tty(tty) => tty.suspend(),
|
||||
Backend::Winit(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle_debug_tint(&mut self) {
|
||||
match self {
|
||||
Backend::Tty(tty) => tty.toggle_debug_tint(),
|
||||
Backend::Winit(winit) => winit.toggle_debug_tint(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tty(&mut self) -> &mut Tty {
|
||||
if let Self::Tty(v) = self {
|
||||
v
|
||||
} else {
|
||||
None
|
||||
panic!("backend is not Tty");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn winit(&mut self) -> &mut Winit {
|
||||
if let Self::Winit(v) = self {
|
||||
v
|
||||
} else {
|
||||
panic!("backend is not Winit")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+56
-68
@@ -30,16 +30,15 @@ use smithay::utils::DeviceFd;
|
||||
use smithay_drm_extras::drm_scanner::{DrmScanEvent, DrmScanner};
|
||||
use smithay_drm_extras::edid::EdidInfo;
|
||||
|
||||
use crate::input::{BackendAction, CompositorMod};
|
||||
use crate::niri::{Data, OutputRenderElements};
|
||||
use crate::Niri;
|
||||
use crate::niri::OutputRenderElements;
|
||||
use crate::{LoopData, Niri};
|
||||
|
||||
const BACKGROUND_COLOR: [f32; 4] = [0.1, 0.1, 0.1, 1.];
|
||||
const SUPPORTED_COLOR_FORMATS: &[Fourcc] = &[Fourcc::Argb8888, Fourcc::Abgr8888];
|
||||
|
||||
pub struct Tty {
|
||||
session: LibSeatSession,
|
||||
udev_dispatcher: Dispatcher<'static, UdevBackend, Data>,
|
||||
udev_dispatcher: Dispatcher<'static, UdevBackend, LoopData>,
|
||||
primary_gpu_path: PathBuf,
|
||||
output_device: Option<OutputDevice>,
|
||||
}
|
||||
@@ -69,44 +68,45 @@ struct TtyOutputState {
|
||||
}
|
||||
|
||||
impl Tty {
|
||||
pub fn new(event_loop: LoopHandle<'static, Data>) -> Self {
|
||||
pub fn new(event_loop: LoopHandle<'static, LoopData>) -> Self {
|
||||
let (session, notifier) = LibSeatSession::new().unwrap();
|
||||
let seat_name = session.seat();
|
||||
|
||||
let udev_backend = UdevBackend::new(session.seat()).unwrap();
|
||||
let udev_dispatcher = Dispatcher::new(udev_backend, move |event, _, data: &mut Data| {
|
||||
let tty = data.backend.tty().unwrap();
|
||||
let niri = &mut data.niri;
|
||||
let udev_dispatcher =
|
||||
Dispatcher::new(udev_backend, move |event, _, data: &mut LoopData| {
|
||||
let tty = data.state.backend.tty();
|
||||
let niri = &mut data.state.niri;
|
||||
|
||||
match event {
|
||||
UdevEvent::Added { device_id, path } => {
|
||||
if !tty.session.is_active() {
|
||||
debug!("skipping UdevEvent::Added as session is inactive");
|
||||
return;
|
||||
match event {
|
||||
UdevEvent::Added { device_id, path } => {
|
||||
if !tty.session.is_active() {
|
||||
debug!("skipping UdevEvent::Added as session is inactive");
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(err) = tty.device_added(device_id, &path, niri) {
|
||||
warn!("error adding device: {err:?}");
|
||||
}
|
||||
}
|
||||
UdevEvent::Changed { device_id } => {
|
||||
if !tty.session.is_active() {
|
||||
debug!("skipping UdevEvent::Changed as session is inactive");
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(err) = tty.device_added(device_id, &path, niri) {
|
||||
warn!("error adding device: {err:?}");
|
||||
tty.device_changed(device_id, niri)
|
||||
}
|
||||
UdevEvent::Removed { device_id } => {
|
||||
if !tty.session.is_active() {
|
||||
debug!("skipping UdevEvent::Removed as session is inactive");
|
||||
return;
|
||||
}
|
||||
|
||||
tty.device_removed(device_id, niri)
|
||||
}
|
||||
}
|
||||
UdevEvent::Changed { device_id } => {
|
||||
if !tty.session.is_active() {
|
||||
debug!("skipping UdevEvent::Changed as session is inactive");
|
||||
return;
|
||||
}
|
||||
|
||||
tty.device_changed(device_id, niri)
|
||||
}
|
||||
UdevEvent::Removed { device_id } => {
|
||||
if !tty.session.is_active() {
|
||||
debug!("skipping UdevEvent::Removed as session is inactive");
|
||||
return;
|
||||
}
|
||||
|
||||
tty.device_removed(device_id, niri)
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
event_loop
|
||||
.register_dispatcher(udev_dispatcher.clone())
|
||||
.unwrap();
|
||||
@@ -117,43 +117,16 @@ impl Tty {
|
||||
let input_backend = LibinputInputBackend::new(libinput.clone());
|
||||
event_loop
|
||||
.insert_source(input_backend, |mut event, _, data| {
|
||||
let tty = data.backend.tty().unwrap();
|
||||
let niri = &mut data.niri;
|
||||
|
||||
niri.process_libinput_event(&mut event);
|
||||
match niri.process_input_event(CompositorMod::Super, event) {
|
||||
BackendAction::None => (),
|
||||
BackendAction::ChangeVt(vt) => tty.change_vt(vt),
|
||||
BackendAction::Suspend => {
|
||||
if let Err(err) = suspend() {
|
||||
warn!("error suspending: {err:?}");
|
||||
}
|
||||
}
|
||||
BackendAction::Screenshot => {
|
||||
let active = niri.monitor_set.active_output().cloned();
|
||||
if let Some(active) = active {
|
||||
if let Err(err) = niri.screenshot(tty.renderer(), &active) {
|
||||
warn!("error taking screenshot: {err:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
BackendAction::ToggleDebugTint => {
|
||||
if let Some(device) = tty.output_device.as_mut() {
|
||||
for (_, compositor) in &mut device.surfaces {
|
||||
compositor
|
||||
.set_debug_flags(compositor.debug_flags() ^ DebugFlags::TINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
data.state.process_libinput_event(&mut event);
|
||||
data.state.process_input_event(event);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let udev_dispatcher_c = udev_dispatcher.clone();
|
||||
event_loop
|
||||
.insert_source(notifier, move |event, _, data| {
|
||||
let tty = data.backend.tty().unwrap();
|
||||
let niri = &mut data.niri;
|
||||
let tty = data.state.backend.tty();
|
||||
let niri = &mut data.state.niri;
|
||||
|
||||
match event {
|
||||
SessionEvent::PauseSession => {
|
||||
@@ -289,7 +262,7 @@ impl Tty {
|
||||
let token = niri
|
||||
.event_loop
|
||||
.insert_source(drm_notifier, move |event, metadata, data| {
|
||||
let tty = data.backend.tty().unwrap();
|
||||
let tty = data.state.backend.tty();
|
||||
match event {
|
||||
DrmEvent::VBlank(crtc) => {
|
||||
tracy_client::Client::running()
|
||||
@@ -336,6 +309,7 @@ impl Tty {
|
||||
}
|
||||
|
||||
let output = data
|
||||
.state
|
||||
.niri
|
||||
.global_space
|
||||
.outputs()
|
||||
@@ -345,10 +319,10 @@ impl Tty {
|
||||
})
|
||||
.unwrap()
|
||||
.clone();
|
||||
let output_state = data.niri.output_state.get_mut(&output).unwrap();
|
||||
let output_state = data.state.niri.output_state.get_mut(&output).unwrap();
|
||||
output_state.waiting_for_vblank = false;
|
||||
output_state.frame_clock.presented(presentation_time);
|
||||
data.niri.queue_redraw(output);
|
||||
data.state.niri.queue_redraw(output);
|
||||
}
|
||||
DrmEvent::Error(error) => error!("DRM error: {error}"),
|
||||
};
|
||||
@@ -589,11 +563,25 @@ impl Tty {
|
||||
}
|
||||
}
|
||||
|
||||
fn change_vt(&mut self, vt: i32) {
|
||||
pub fn change_vt(&mut self, vt: i32) {
|
||||
if let Err(err) = self.session.change_vt(vt) {
|
||||
error!("error changing VT: {err}");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn suspend(&self) {
|
||||
if let Err(err) = suspend() {
|
||||
warn!("error suspending: {err:?}");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle_debug_tint(&mut self) {
|
||||
if let Some(device) = self.output_device.as_mut() {
|
||||
for (_, compositor) in &mut device.surfaces {
|
||||
compositor.set_debug_flags(compositor.debug_flags() ^ DebugFlags::TINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn refresh_interval(mode: DrmMode) -> Duration {
|
||||
|
||||
+43
-60
@@ -3,7 +3,7 @@ use std::time::Duration;
|
||||
use smithay::backend::renderer::damage::OutputDamageTracker;
|
||||
use smithay::backend::renderer::gles::GlesRenderer;
|
||||
use smithay::backend::renderer::{DebugFlags, Renderer};
|
||||
use smithay::backend::winit::{self, WinitError, WinitEvent, WinitEventLoop, WinitGraphicsBackend};
|
||||
use smithay::backend::winit::{self, WinitError, WinitEvent, WinitGraphicsBackend};
|
||||
use smithay::output::{Mode, Output, PhysicalProperties, Subpixel};
|
||||
use smithay::reexports::calloop::timer::{TimeoutAction, Timer};
|
||||
use smithay::reexports::calloop::LoopHandle;
|
||||
@@ -12,25 +12,23 @@ use smithay::reexports::winit::dpi::LogicalSize;
|
||||
use smithay::reexports::winit::window::WindowBuilder;
|
||||
use smithay::utils::Transform;
|
||||
|
||||
use crate::input::{BackendAction, CompositorMod};
|
||||
use crate::niri::{Data, OutputRenderElements};
|
||||
use crate::niri::OutputRenderElements;
|
||||
use crate::utils::get_monotonic_time;
|
||||
use crate::Niri;
|
||||
use crate::{LoopData, Niri};
|
||||
|
||||
pub struct Winit {
|
||||
output: Output,
|
||||
backend: WinitGraphicsBackend<GlesRenderer>,
|
||||
winit_event_loop: WinitEventLoop,
|
||||
damage_tracker: OutputDamageTracker,
|
||||
}
|
||||
|
||||
impl Winit {
|
||||
pub fn new(event_loop: LoopHandle<Data>) -> Self {
|
||||
pub fn new(event_loop: LoopHandle<LoopData>) -> Self {
|
||||
let builder = WindowBuilder::new()
|
||||
.with_inner_size(LogicalSize::new(1280.0, 800.0))
|
||||
// .with_resizable(false)
|
||||
.with_title("niri");
|
||||
let (backend, winit_event_loop) = winit::init_from_builder(builder).unwrap();
|
||||
let (backend, mut winit_event_loop) = winit::init_from_builder(builder).unwrap();
|
||||
|
||||
let mode = Mode {
|
||||
size: backend.window_size().physical_size,
|
||||
@@ -59,8 +57,39 @@ impl Winit {
|
||||
let timer = Timer::immediate();
|
||||
event_loop
|
||||
.insert_source(timer, move |_, _, data| {
|
||||
let winit = data.backend.winit().unwrap();
|
||||
winit.dispatch(&mut data.niri);
|
||||
let res = winit_event_loop.dispatch_new_events(|event| match event {
|
||||
WinitEvent::Resized { size, .. } => {
|
||||
let winit = data.state.backend.winit();
|
||||
winit.output.change_current_state(
|
||||
Some(Mode {
|
||||
size,
|
||||
refresh: 60_000,
|
||||
}),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
data.state.niri.output_resized(winit.output.clone());
|
||||
}
|
||||
WinitEvent::Input(event) => data.state.process_input_event(event),
|
||||
WinitEvent::Focus(_) => (),
|
||||
WinitEvent::Refresh => data
|
||||
.state
|
||||
.niri
|
||||
.queue_redraw(data.state.backend.winit().output.clone()),
|
||||
});
|
||||
|
||||
// I want this to stop compiling if more errors are added.
|
||||
#[allow(clippy::single_match)]
|
||||
match res {
|
||||
Err(WinitError::WindowClosed) => {
|
||||
data.state.niri.stop_signal.stop();
|
||||
data.state
|
||||
.niri
|
||||
.remove_output(&data.state.backend.winit().output);
|
||||
}
|
||||
Ok(()) => (),
|
||||
}
|
||||
TimeoutAction::ToDuration(Duration::from_micros(16667))
|
||||
})
|
||||
.unwrap();
|
||||
@@ -68,7 +97,6 @@ impl Winit {
|
||||
Self {
|
||||
output,
|
||||
backend,
|
||||
winit_event_loop,
|
||||
damage_tracker,
|
||||
}
|
||||
}
|
||||
@@ -88,56 +116,6 @@ impl Winit {
|
||||
niri.add_output(self.output.clone(), None);
|
||||
}
|
||||
|
||||
fn dispatch(&mut self, niri: &mut Niri) {
|
||||
let renderer = self.backend.renderer();
|
||||
let res = self
|
||||
.winit_event_loop
|
||||
.dispatch_new_events(|event| match event {
|
||||
WinitEvent::Resized { size, .. } => {
|
||||
self.output.change_current_state(
|
||||
Some(Mode {
|
||||
size,
|
||||
refresh: 60_000,
|
||||
}),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
niri.output_resized(self.output.clone());
|
||||
}
|
||||
WinitEvent::Input(event) => {
|
||||
match niri.process_input_event(CompositorMod::Alt, event) {
|
||||
BackendAction::None => (),
|
||||
BackendAction::ChangeVt(_) => (),
|
||||
BackendAction::Suspend => (),
|
||||
BackendAction::Screenshot => {
|
||||
let active = niri.monitor_set.active_output().cloned();
|
||||
if let Some(active) = active {
|
||||
if let Err(err) = niri.screenshot(renderer, &active) {
|
||||
warn!("error taking screenshot: {err:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
BackendAction::ToggleDebugTint => {
|
||||
renderer.set_debug_flags(renderer.debug_flags() ^ DebugFlags::TINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
WinitEvent::Focus(_) => (),
|
||||
WinitEvent::Refresh => niri.queue_redraw(self.output.clone()),
|
||||
});
|
||||
|
||||
// I want this to stop compiling if more errors are added.
|
||||
#[allow(clippy::single_match)]
|
||||
match res {
|
||||
Err(WinitError::WindowClosed) => {
|
||||
niri.stop_signal.stop();
|
||||
niri.remove_output(&self.output);
|
||||
}
|
||||
Ok(()) => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn seat_name(&self) -> String {
|
||||
"winit".to_owned()
|
||||
}
|
||||
@@ -175,4 +153,9 @@ impl Winit {
|
||||
self.backend.window().request_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle_debug_tint(&mut self) {
|
||||
let renderer = self.backend.renderer();
|
||||
renderer.set_debug_flags(renderer.debug_flags() ^ DebugFlags::TINT);
|
||||
}
|
||||
}
|
||||
|
||||
+26
-25
@@ -13,12 +13,11 @@ use smithay::wayland::shm::{ShmHandler, ShmState};
|
||||
use smithay::{delegate_compositor, delegate_shm};
|
||||
|
||||
use super::xdg_shell;
|
||||
use crate::niri::ClientState;
|
||||
use crate::Niri;
|
||||
use crate::niri::{ClientState, State};
|
||||
|
||||
impl CompositorHandler for Niri {
|
||||
impl CompositorHandler for State {
|
||||
fn compositor_state(&mut self) -> &mut CompositorState {
|
||||
&mut self.compositor_state
|
||||
&mut self.niri.compositor_state
|
||||
}
|
||||
|
||||
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
|
||||
@@ -41,7 +40,7 @@ impl CompositorHandler for Niri {
|
||||
|
||||
if surface == &root_surface {
|
||||
// This is a root surface commit. It might have mapped a previously-unmapped toplevel.
|
||||
if let Entry::Occupied(entry) = self.unmapped_windows.entry(surface.clone()) {
|
||||
if let Entry::Occupied(entry) = self.niri.unmapped_windows.entry(surface.clone()) {
|
||||
let is_mapped =
|
||||
with_renderer_surface_state(surface, |state| state.buffer().is_some());
|
||||
|
||||
@@ -50,9 +49,11 @@ impl CompositorHandler for Niri {
|
||||
let window = entry.remove();
|
||||
window.on_commit();
|
||||
|
||||
let output = self.monitor_set.active_output().unwrap().clone();
|
||||
self.monitor_set.add_window_to_output(&output, window, true);
|
||||
self.queue_redraw(output);
|
||||
let output = self.niri.monitor_set.active_output().unwrap().clone();
|
||||
self.niri
|
||||
.monitor_set
|
||||
.add_window_to_output(&output, window, true);
|
||||
self.niri.queue_redraw(output);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -63,7 +64,7 @@ impl CompositorHandler for Niri {
|
||||
}
|
||||
|
||||
// This is a commit of a previously-mapped root or a non-toplevel root.
|
||||
if let Some((window, output)) = self.monitor_set.find_window_and_output(surface) {
|
||||
if let Some((window, output)) = self.niri.monitor_set.find_window_and_output(surface) {
|
||||
// This is a commit of a previously-mapped toplevel.
|
||||
window.on_commit();
|
||||
|
||||
@@ -73,16 +74,16 @@ impl CompositorHandler for Niri {
|
||||
|
||||
if !is_mapped {
|
||||
// The toplevel got unmapped.
|
||||
self.monitor_set.remove_window(&window);
|
||||
self.unmapped_windows.insert(surface.clone(), window);
|
||||
self.queue_redraw(output);
|
||||
self.niri.monitor_set.remove_window(&window);
|
||||
self.niri.unmapped_windows.insert(surface.clone(), window);
|
||||
self.niri.queue_redraw(output);
|
||||
return;
|
||||
}
|
||||
|
||||
// The toplevel remains mapped.
|
||||
self.monitor_set.update_window(&window);
|
||||
self.niri.monitor_set.update_window(&window);
|
||||
|
||||
self.queue_redraw(output);
|
||||
self.niri.queue_redraw(output);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -90,21 +91,21 @@ impl CompositorHandler for Niri {
|
||||
}
|
||||
|
||||
// This is a commit of a non-root or a non-toplevel root.
|
||||
let root_window_output = self.monitor_set.find_window_and_output(&root_surface);
|
||||
let root_window_output = self.niri.monitor_set.find_window_and_output(&root_surface);
|
||||
if let Some((window, output)) = root_window_output {
|
||||
window.on_commit();
|
||||
self.monitor_set.update_window(&window);
|
||||
self.queue_redraw(output);
|
||||
self.niri.monitor_set.update_window(&window);
|
||||
self.niri.queue_redraw(output);
|
||||
return;
|
||||
}
|
||||
|
||||
// This might be a popup.
|
||||
self.popups_handle_commit(surface);
|
||||
if let Some(popup) = self.popups.find_popup(surface) {
|
||||
if let Some(popup) = self.niri.popups.find_popup(surface) {
|
||||
if let Ok(root) = find_popup_root_surface(&popup) {
|
||||
let root_window_output = self.monitor_set.find_window_and_output(&root);
|
||||
let root_window_output = self.niri.monitor_set.find_window_and_output(&root);
|
||||
if let Some((_window, output)) = root_window_output {
|
||||
self.queue_redraw(output);
|
||||
self.niri.queue_redraw(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,15 +115,15 @@ impl CompositorHandler for Niri {
|
||||
}
|
||||
}
|
||||
|
||||
impl BufferHandler for Niri {
|
||||
impl BufferHandler for State {
|
||||
fn buffer_destroyed(&mut self, _buffer: &wl_buffer::WlBuffer) {}
|
||||
}
|
||||
|
||||
impl ShmHandler for Niri {
|
||||
impl ShmHandler for State {
|
||||
fn shm_state(&self) -> &ShmState {
|
||||
&self.shm_state
|
||||
&self.niri.shm_state
|
||||
}
|
||||
}
|
||||
|
||||
delegate_compositor!(Niri);
|
||||
delegate_shm!(Niri);
|
||||
delegate_compositor!(State);
|
||||
delegate_shm!(State);
|
||||
|
||||
@@ -9,11 +9,11 @@ use smithay::wayland::shell::wlr_layer::{
|
||||
WlrLayerShellState,
|
||||
};
|
||||
|
||||
use crate::niri::Niri;
|
||||
use crate::niri::State;
|
||||
|
||||
impl WlrLayerShellHandler for Niri {
|
||||
impl WlrLayerShellHandler for State {
|
||||
fn shell_state(&mut self) -> &mut WlrLayerShellState {
|
||||
&mut self.layer_shell_state
|
||||
&mut self.niri.layer_shell_state
|
||||
}
|
||||
|
||||
fn new_layer_surface(
|
||||
@@ -26,7 +26,7 @@ impl WlrLayerShellHandler for Niri {
|
||||
let output = wl_output
|
||||
.as_ref()
|
||||
.and_then(Output::from_resource)
|
||||
.or_else(|| self.monitor_set.active_output().cloned())
|
||||
.or_else(|| self.niri.monitor_set.active_output().cloned())
|
||||
.unwrap();
|
||||
let mut map = layer_map_for_output(&output);
|
||||
map.map_layer(&LayerSurface::new(surface, namespace))
|
||||
@@ -35,7 +35,7 @@ impl WlrLayerShellHandler for Niri {
|
||||
|
||||
fn layer_destroyed(&mut self, surface: WlrLayerSurface) {
|
||||
let output = if let Some((output, mut map, layer)) =
|
||||
self.monitor_set.outputs().find_map(|o| {
|
||||
self.niri.monitor_set.outputs().find_map(|o| {
|
||||
let map = layer_map_for_output(o);
|
||||
let layer = map
|
||||
.layers()
|
||||
@@ -49,15 +49,16 @@ impl WlrLayerShellHandler for Niri {
|
||||
None
|
||||
};
|
||||
if let Some(output) = output {
|
||||
self.queue_redraw(output);
|
||||
self.niri.queue_redraw(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate_layer_shell!(Niri);
|
||||
delegate_layer_shell!(State);
|
||||
|
||||
impl Niri {
|
||||
impl State {
|
||||
pub fn layer_shell_handle_commit(&mut self, surface: &WlSurface) {
|
||||
let Some(output) = self
|
||||
.niri
|
||||
.monitor_set
|
||||
.outputs()
|
||||
.find(|o| {
|
||||
@@ -95,6 +96,6 @@ impl Niri {
|
||||
}
|
||||
drop(map);
|
||||
|
||||
self.queue_redraw(output);
|
||||
self.niri.queue_redraw(output);
|
||||
}
|
||||
}
|
||||
|
||||
+21
-21
@@ -16,62 +16,62 @@ use smithay::{
|
||||
delegate_seat, delegate_tablet_manager,
|
||||
};
|
||||
|
||||
use crate::Niri;
|
||||
use crate::niri::State;
|
||||
|
||||
impl SeatHandler for Niri {
|
||||
impl SeatHandler for State {
|
||||
type KeyboardFocus = WlSurface;
|
||||
type PointerFocus = WlSurface;
|
||||
|
||||
fn seat_state(&mut self) -> &mut SeatState<Niri> {
|
||||
&mut self.seat_state
|
||||
fn seat_state(&mut self) -> &mut SeatState<State> {
|
||||
&mut self.niri.seat_state
|
||||
}
|
||||
|
||||
fn cursor_image(&mut self, _seat: &Seat<Self>, image: CursorImageStatus) {
|
||||
self.cursor_image = image;
|
||||
self.niri.cursor_image = image;
|
||||
// FIXME: more granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
|
||||
fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&WlSurface>) {
|
||||
let dh = &self.display_handle;
|
||||
let dh = &self.niri.display_handle;
|
||||
let client = focused.and_then(|s| dh.get_client(s.id()).ok());
|
||||
set_data_device_focus(dh, seat, client);
|
||||
}
|
||||
}
|
||||
delegate_seat!(Niri);
|
||||
delegate_tablet_manager!(Niri);
|
||||
delegate_pointer_gestures!(Niri);
|
||||
delegate_seat!(State);
|
||||
delegate_tablet_manager!(State);
|
||||
delegate_pointer_gestures!(State);
|
||||
|
||||
impl DataDeviceHandler for Niri {
|
||||
impl DataDeviceHandler for State {
|
||||
type SelectionUserData = ();
|
||||
fn data_device_state(&self) -> &DataDeviceState {
|
||||
&self.data_device_state
|
||||
&self.niri.data_device_state
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientDndGrabHandler for Niri {
|
||||
impl ClientDndGrabHandler for State {
|
||||
fn started(
|
||||
&mut self,
|
||||
_source: Option<WlDataSource>,
|
||||
icon: Option<WlSurface>,
|
||||
_seat: Seat<Self>,
|
||||
) {
|
||||
self.dnd_icon = icon;
|
||||
self.niri.dnd_icon = icon;
|
||||
// FIXME: more granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
|
||||
fn dropped(&mut self, _seat: Seat<Self>) {
|
||||
self.dnd_icon = None;
|
||||
self.niri.dnd_icon = None;
|
||||
// FIXME: more granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
}
|
||||
|
||||
impl ServerDndGrabHandler for Niri {}
|
||||
impl ServerDndGrabHandler for State {}
|
||||
|
||||
delegate_data_device!(Niri);
|
||||
delegate_data_device!(State);
|
||||
|
||||
delegate_output!(Niri);
|
||||
delegate_output!(State);
|
||||
|
||||
delegate_presentation!(Niri);
|
||||
delegate_presentation!(State);
|
||||
|
||||
+27
-18
@@ -13,11 +13,11 @@ use smithay::wayland::shell::xdg::{
|
||||
};
|
||||
|
||||
use crate::layout::{configure_new_window, output_size};
|
||||
use crate::Niri;
|
||||
use crate::niri::State;
|
||||
|
||||
impl XdgShellHandler for Niri {
|
||||
impl XdgShellHandler for State {
|
||||
fn xdg_shell_state(&mut self) -> &mut XdgShellState {
|
||||
&mut self.xdg_shell_state
|
||||
&mut self.niri.xdg_shell_state
|
||||
}
|
||||
|
||||
fn new_toplevel(&mut self, surface: ToplevelSurface) {
|
||||
@@ -25,18 +25,18 @@ impl XdgShellHandler for Niri {
|
||||
let window = Window::new(surface);
|
||||
|
||||
// Tell the surface the preferred size and bounds for its likely output.
|
||||
let output = self.monitor_set.active_output().unwrap();
|
||||
let output = self.niri.monitor_set.active_output().unwrap();
|
||||
configure_new_window(output_size(output), &window);
|
||||
|
||||
// At the moment of creation, xdg toplevels must have no buffer.
|
||||
let existing = self.unmapped_windows.insert(wl_surface, window);
|
||||
let existing = self.niri.unmapped_windows.insert(wl_surface, window);
|
||||
assert!(existing.is_none());
|
||||
}
|
||||
|
||||
fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) {
|
||||
// FIXME: adjust the geometry so the popup doesn't overflow at least off the top and bottom
|
||||
// screen edges, and ideally off the view size.
|
||||
if let Err(err) = self.popups.track_popup(PopupKind::Xdg(surface)) {
|
||||
if let Err(err) = self.niri.popups.track_popup(PopupKind::Xdg(surface)) {
|
||||
warn!("error tracking popup: {err:?}");
|
||||
}
|
||||
}
|
||||
@@ -101,17 +101,19 @@ impl XdgShellHandler for Niri {
|
||||
// location and configure size here, but the surface should be rendered fullscreen
|
||||
// independently from its buffer size
|
||||
if let Some((window, current_output)) = self
|
||||
.niri
|
||||
.monitor_set
|
||||
.find_window_and_output(surface.wl_surface())
|
||||
{
|
||||
if let Some(requested_output) = wl_output.as_ref().and_then(Output::from_resource) {
|
||||
if requested_output != current_output {
|
||||
self.monitor_set
|
||||
self.niri
|
||||
.monitor_set
|
||||
.move_window_to_output(window.clone(), &requested_output);
|
||||
}
|
||||
}
|
||||
|
||||
self.monitor_set.set_fullscreen(&window, true);
|
||||
self.niri.monitor_set.set_fullscreen(&window, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,38 +124,45 @@ impl XdgShellHandler for Niri {
|
||||
|
||||
fn unfullscreen_request(&mut self, surface: ToplevelSurface) {
|
||||
if let Some((window, _)) = self
|
||||
.niri
|
||||
.monitor_set
|
||||
.find_window_and_output(surface.wl_surface())
|
||||
{
|
||||
self.monitor_set.set_fullscreen(&window, false);
|
||||
self.niri.monitor_set.set_fullscreen(&window, false);
|
||||
}
|
||||
}
|
||||
|
||||
fn toplevel_destroyed(&mut self, surface: ToplevelSurface) {
|
||||
if self.unmapped_windows.remove(surface.wl_surface()).is_some() {
|
||||
if self
|
||||
.niri
|
||||
.unmapped_windows
|
||||
.remove(surface.wl_surface())
|
||||
.is_some()
|
||||
{
|
||||
// An unmapped toplevel got destroyed.
|
||||
return;
|
||||
}
|
||||
|
||||
let (window, output) = self
|
||||
.niri
|
||||
.monitor_set
|
||||
.find_window_and_output(surface.wl_surface())
|
||||
.unwrap();
|
||||
self.monitor_set.remove_window(&window);
|
||||
self.queue_redraw(output);
|
||||
self.niri.monitor_set.remove_window(&window);
|
||||
self.niri.queue_redraw(output);
|
||||
}
|
||||
|
||||
fn popup_destroyed(&mut self, surface: PopupSurface) {
|
||||
if let Ok(root) = find_popup_root_surface(&surface.into()) {
|
||||
let root_window_output = self.monitor_set.find_window_and_output(&root);
|
||||
let root_window_output = self.niri.monitor_set.find_window_and_output(&root);
|
||||
if let Some((_window, output)) = root_window_output {
|
||||
self.queue_redraw(output);
|
||||
self.niri.queue_redraw(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delegate_xdg_shell!(Niri);
|
||||
delegate_xdg_shell!(State);
|
||||
|
||||
pub fn send_initial_configure_if_needed(window: &Window) {
|
||||
let initial_configure_sent = with_states(window.toplevel().wl_surface(), |states| {
|
||||
@@ -171,12 +180,12 @@ pub fn send_initial_configure_if_needed(window: &Window) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Niri {
|
||||
impl State {
|
||||
/// Should be called on `WlSurface::commit`
|
||||
pub fn popups_handle_commit(&mut self, surface: &WlSurface) {
|
||||
self.popups.commit(surface);
|
||||
self.niri.popups.commit(surface);
|
||||
|
||||
if let Some(popup) = self.popups.find_popup(surface) {
|
||||
if let Some(popup) = self.niri.popups.find_popup(surface) {
|
||||
let PopupKind::Xdg(ref popup) = popup;
|
||||
let initial_configure_sent = with_states(surface, |states| {
|
||||
states
|
||||
|
||||
+114
-116
@@ -17,7 +17,7 @@ use smithay::input::pointer::{
|
||||
use smithay::utils::SERIAL_COUNTER;
|
||||
use smithay::wayland::tablet_manager::{TabletDescriptor, TabletSeatTrait};
|
||||
|
||||
use crate::niri::Niri;
|
||||
use crate::niri::State;
|
||||
use crate::utils::get_monotonic_time;
|
||||
|
||||
enum Action {
|
||||
@@ -56,14 +56,6 @@ enum Action {
|
||||
ToggleFullWidth,
|
||||
}
|
||||
|
||||
pub enum BackendAction {
|
||||
None,
|
||||
ChangeVt(i32),
|
||||
Suspend,
|
||||
Screenshot,
|
||||
ToggleDebugTint,
|
||||
}
|
||||
|
||||
pub enum CompositorMod {
|
||||
Super,
|
||||
Alt,
|
||||
@@ -148,12 +140,8 @@ fn action(comp_mod: CompositorMod, keysym: KeysymHandle, mods: ModifiersState) -
|
||||
}
|
||||
}
|
||||
|
||||
impl Niri {
|
||||
pub fn process_input_event<I: InputBackend>(
|
||||
&mut self,
|
||||
comp_mod: CompositorMod,
|
||||
event: InputEvent<I>,
|
||||
) -> BackendAction {
|
||||
impl State {
|
||||
pub fn process_input_event<I: InputBackend>(&mut self, event: InputEvent<I>) {
|
||||
let _span = tracy_client::span!("process_input_event");
|
||||
trace!("process_input_event");
|
||||
|
||||
@@ -161,14 +149,18 @@ impl Niri {
|
||||
// doesn't always trigger due to damage, etc. So run it here right before it might prove
|
||||
// important. Besides, animations affect the input, so it's best to have up-to-date values
|
||||
// here.
|
||||
self.monitor_set.advance_animations(get_monotonic_time());
|
||||
self.niri
|
||||
.monitor_set
|
||||
.advance_animations(get_monotonic_time());
|
||||
|
||||
let comp_mod = self.backend.mod_key();
|
||||
|
||||
match event {
|
||||
InputEvent::Keyboard { event, .. } => {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
let time = Event::time_msec(&event);
|
||||
|
||||
let action = self.seat.get_keyboard().unwrap().input(
|
||||
let action = self.niri.seat.get_keyboard().unwrap().input(
|
||||
self,
|
||||
event.key_code(),
|
||||
event.state(),
|
||||
@@ -188,16 +180,16 @@ impl Niri {
|
||||
Action::None => unreachable!(),
|
||||
Action::Quit => {
|
||||
info!("quitting because quit bind was pressed");
|
||||
self.stop_signal.stop()
|
||||
self.niri.stop_signal.stop()
|
||||
}
|
||||
Action::ChangeVt(vt) => {
|
||||
return BackendAction::ChangeVt(vt);
|
||||
self.backend.change_vt(vt);
|
||||
}
|
||||
Action::Suspend => {
|
||||
return BackendAction::Suspend;
|
||||
self.backend.suspend();
|
||||
}
|
||||
Action::ToggleDebugTint => {
|
||||
return BackendAction::ToggleDebugTint;
|
||||
self.backend.toggle_debug_tint();
|
||||
}
|
||||
Action::Spawn(command) => {
|
||||
if let Err(err) = Command::new(command).spawn() {
|
||||
@@ -205,132 +197,139 @@ impl Niri {
|
||||
}
|
||||
}
|
||||
Action::Screenshot => {
|
||||
return BackendAction::Screenshot;
|
||||
let active = self.niri.monitor_set.active_output().cloned();
|
||||
if let Some(active) = active {
|
||||
if let Err(err) =
|
||||
self.niri.screenshot(self.backend.renderer(), &active)
|
||||
{
|
||||
warn!("error taking screenshot: {err:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Action::CloseWindow => {
|
||||
if let Some(window) = self.monitor_set.focus() {
|
||||
if let Some(window) = self.niri.monitor_set.focus() {
|
||||
window.toplevel().send_close();
|
||||
}
|
||||
}
|
||||
Action::ToggleFullscreen => {
|
||||
let focus = self.monitor_set.focus().cloned();
|
||||
let focus = self.niri.monitor_set.focus().cloned();
|
||||
if let Some(window) = focus {
|
||||
self.monitor_set.toggle_fullscreen(&window);
|
||||
self.niri.monitor_set.toggle_fullscreen(&window);
|
||||
}
|
||||
}
|
||||
Action::MoveLeft => {
|
||||
self.monitor_set.move_left();
|
||||
self.niri.monitor_set.move_left();
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveRight => {
|
||||
self.monitor_set.move_right();
|
||||
self.niri.monitor_set.move_right();
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveDown => {
|
||||
self.monitor_set.move_down();
|
||||
self.niri.monitor_set.move_down();
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveUp => {
|
||||
self.monitor_set.move_up();
|
||||
self.niri.monitor_set.move_up();
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusLeft => {
|
||||
self.monitor_set.focus_left();
|
||||
self.niri.monitor_set.focus_left();
|
||||
}
|
||||
Action::FocusRight => {
|
||||
self.monitor_set.focus_right();
|
||||
self.niri.monitor_set.focus_right();
|
||||
}
|
||||
Action::FocusDown => {
|
||||
self.monitor_set.focus_down();
|
||||
self.niri.monitor_set.focus_down();
|
||||
}
|
||||
Action::FocusUp => {
|
||||
self.monitor_set.focus_up();
|
||||
self.niri.monitor_set.focus_up();
|
||||
}
|
||||
Action::MoveToWorkspaceDown => {
|
||||
self.monitor_set.move_to_workspace_down();
|
||||
self.niri.monitor_set.move_to_workspace_down();
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveToWorkspaceUp => {
|
||||
self.monitor_set.move_to_workspace_up();
|
||||
self.niri.monitor_set.move_to_workspace_up();
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::SwitchWorkspaceDown => {
|
||||
self.monitor_set.switch_workspace_down();
|
||||
self.niri.monitor_set.switch_workspace_down();
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::SwitchWorkspaceUp => {
|
||||
self.monitor_set.switch_workspace_up();
|
||||
self.niri.monitor_set.switch_workspace_up();
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::ConsumeIntoColumn => {
|
||||
self.monitor_set.consume_into_column();
|
||||
self.niri.monitor_set.consume_into_column();
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::ExpelFromColumn => {
|
||||
self.monitor_set.expel_from_column();
|
||||
self.niri.monitor_set.expel_from_column();
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::ToggleWidth => {
|
||||
self.monitor_set.toggle_width();
|
||||
self.niri.monitor_set.toggle_width();
|
||||
}
|
||||
Action::ToggleFullWidth => {
|
||||
self.monitor_set.toggle_full_width();
|
||||
self.niri.monitor_set.toggle_full_width();
|
||||
}
|
||||
Action::FocusMonitorLeft => {
|
||||
if let Some(output) = self.output_left() {
|
||||
self.monitor_set.focus_output(&output);
|
||||
if let Some(output) = self.niri.output_left() {
|
||||
self.niri.monitor_set.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
Action::FocusMonitorRight => {
|
||||
if let Some(output) = self.output_right() {
|
||||
self.monitor_set.focus_output(&output);
|
||||
if let Some(output) = self.niri.output_right() {
|
||||
self.niri.monitor_set.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
Action::FocusMonitorDown => {
|
||||
if let Some(output) = self.output_down() {
|
||||
self.monitor_set.focus_output(&output);
|
||||
if let Some(output) = self.niri.output_down() {
|
||||
self.niri.monitor_set.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
Action::FocusMonitorUp => {
|
||||
if let Some(output) = self.output_up() {
|
||||
self.monitor_set.focus_output(&output);
|
||||
if let Some(output) = self.niri.output_up() {
|
||||
self.niri.monitor_set.focus_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
Action::MoveToMonitorLeft => {
|
||||
if let Some(output) = self.output_left() {
|
||||
self.monitor_set.move_to_output(&output);
|
||||
if let Some(output) = self.niri.output_left() {
|
||||
self.niri.monitor_set.move_to_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
Action::MoveToMonitorRight => {
|
||||
if let Some(output) = self.output_right() {
|
||||
self.monitor_set.move_to_output(&output);
|
||||
if let Some(output) = self.niri.output_right() {
|
||||
self.niri.monitor_set.move_to_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
Action::MoveToMonitorDown => {
|
||||
if let Some(output) = self.output_down() {
|
||||
self.monitor_set.move_to_output(&output);
|
||||
if let Some(output) = self.niri.output_down() {
|
||||
self.niri.monitor_set.move_to_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
Action::MoveToMonitorUp => {
|
||||
if let Some(output) = self.output_up() {
|
||||
self.monitor_set.move_to_output(&output);
|
||||
if let Some(output) = self.niri.output_up() {
|
||||
self.niri.monitor_set.move_to_output(&output);
|
||||
self.move_cursor_to_output(&output);
|
||||
}
|
||||
}
|
||||
@@ -340,7 +339,7 @@ impl Niri {
|
||||
InputEvent::PointerMotion { event, .. } => {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
let mut pos = pointer.current_location();
|
||||
|
||||
pos += event.delta();
|
||||
@@ -349,9 +348,9 @@ impl Niri {
|
||||
let mut min_y = i32::MAX;
|
||||
let mut max_x = 0;
|
||||
let mut max_y = 0;
|
||||
for output in self.global_space.outputs() {
|
||||
for output in self.niri.global_space.outputs() {
|
||||
// FIXME: smarter clamping.
|
||||
let geom = self.global_space.output_geometry(output).unwrap();
|
||||
let geom = self.niri.global_space.output_geometry(output).unwrap();
|
||||
min_x = min_x.min(geom.loc.x);
|
||||
min_y = min_y.min(geom.loc.y);
|
||||
max_x = max_x.max(geom.loc.x + geom.size.w);
|
||||
@@ -361,7 +360,7 @@ impl Niri {
|
||||
pos.x = pos.x.clamp(min_x as f64, max_x as f64);
|
||||
pos.y = pos.y.clamp(min_y as f64, max_y as f64);
|
||||
|
||||
let under = self.surface_under_and_global_space(pos);
|
||||
let under = self.niri.surface_under_and_global_space(pos);
|
||||
|
||||
pointer.motion(
|
||||
self,
|
||||
@@ -385,20 +384,20 @@ impl Niri {
|
||||
|
||||
// Redraw to update the cursor position.
|
||||
// FIXME: redraw only outputs overlapping the cursor.
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
InputEvent::PointerMotionAbsolute { event, .. } => {
|
||||
let output = self.global_space.outputs().next().unwrap();
|
||||
let output = self.niri.global_space.outputs().next().unwrap();
|
||||
|
||||
let output_geo = self.global_space.output_geometry(output).unwrap();
|
||||
let output_geo = self.niri.global_space.output_geometry(output).unwrap();
|
||||
|
||||
let pos = event.position_transformed(output_geo.size) + output_geo.loc.to_f64();
|
||||
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
|
||||
let under = self.surface_under_and_global_space(pos);
|
||||
let under = self.niri.surface_under_and_global_space(pos);
|
||||
|
||||
pointer.motion(
|
||||
self,
|
||||
@@ -412,10 +411,10 @@ impl Niri {
|
||||
|
||||
// Redraw to update the cursor position.
|
||||
// FIXME: redraw only outputs overlapping the cursor.
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
InputEvent::PointerButton { event, .. } => {
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
|
||||
@@ -424,12 +423,12 @@ impl Niri {
|
||||
let button_state = event.state();
|
||||
|
||||
if ButtonState::Pressed == button_state && !pointer.is_grabbed() {
|
||||
if let Some(window) = self.window_under_cursor() {
|
||||
if let Some(window) = self.niri.window_under_cursor() {
|
||||
let window = window.clone();
|
||||
self.monitor_set.activate_window(&window);
|
||||
self.niri.monitor_set.activate_window(&window);
|
||||
} else {
|
||||
let output = self.output_under_cursor().unwrap();
|
||||
self.monitor_set.activate_output(&output);
|
||||
let output = self.niri.output_under_cursor().unwrap();
|
||||
self.niri.monitor_set.activate_output(&output);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -473,21 +472,21 @@ impl Niri {
|
||||
frame = frame.stop(Axis::Vertical);
|
||||
}
|
||||
|
||||
self.seat.get_pointer().unwrap().axis(self, frame);
|
||||
self.niri.seat.get_pointer().unwrap().axis(self, frame);
|
||||
}
|
||||
InputEvent::TabletToolAxis { event, .. } => {
|
||||
// FIXME: allow mapping tablet to different outputs.
|
||||
let output = self.global_space.outputs().next().unwrap();
|
||||
let output = self.niri.global_space.outputs().next().unwrap();
|
||||
|
||||
let output_geo = self.global_space.output_geometry(output).unwrap();
|
||||
let output_geo = self.niri.global_space.output_geometry(output).unwrap();
|
||||
|
||||
let pos = event.position_transformed(output_geo.size) + output_geo.loc.to_f64();
|
||||
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
|
||||
let under = self.surface_under_and_global_space(pos);
|
||||
let under = self.niri.surface_under_and_global_space(pos);
|
||||
|
||||
pointer.motion(
|
||||
self,
|
||||
@@ -499,7 +498,7 @@ impl Niri {
|
||||
},
|
||||
);
|
||||
|
||||
let tablet_seat = self.seat.tablet_seat();
|
||||
let tablet_seat = self.niri.seat.tablet_seat();
|
||||
let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&event.device()));
|
||||
let tool = tablet_seat.get_tool(&event.tool());
|
||||
if let (Some(tablet), Some(tool)) = (tablet, tool) {
|
||||
@@ -533,10 +532,10 @@ impl Niri {
|
||||
|
||||
// Redraw to update the cursor position.
|
||||
// FIXME: redraw only outputs overlapping the cursor.
|
||||
self.queue_redraw_all();
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
InputEvent::TabletToolTip { event, .. } => {
|
||||
let tool = self.seat.tablet_seat().get_tool(&event.tool());
|
||||
let tool = self.niri.seat.tablet_seat().get_tool(&event.tool());
|
||||
|
||||
if let Some(tool) = tool {
|
||||
match event.tip_state() {
|
||||
@@ -544,14 +543,14 @@ impl Niri {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
tool.tip_down(serial, event.time_msec());
|
||||
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
if !pointer.is_grabbed() {
|
||||
if let Some(window) = self.window_under_cursor() {
|
||||
if let Some(window) = self.niri.window_under_cursor() {
|
||||
let window = window.clone();
|
||||
self.monitor_set.activate_window(&window);
|
||||
self.niri.monitor_set.activate_window(&window);
|
||||
} else {
|
||||
let output = self.output_under_cursor().unwrap();
|
||||
self.monitor_set.activate_output(&output);
|
||||
let output = self.niri.output_under_cursor().unwrap();
|
||||
self.niri.monitor_set.activate_output(&output);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -563,17 +562,17 @@ impl Niri {
|
||||
}
|
||||
InputEvent::TabletToolProximity { event, .. } => {
|
||||
// FIXME: allow mapping tablet to different outputs.
|
||||
let output = self.global_space.outputs().next().unwrap();
|
||||
let output = self.niri.global_space.outputs().next().unwrap();
|
||||
|
||||
let output_geo = self.global_space.output_geometry(output).unwrap();
|
||||
let output_geo = self.niri.global_space.output_geometry(output).unwrap();
|
||||
|
||||
let pos = event.position_transformed(output_geo.size) + output_geo.loc.to_f64();
|
||||
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
|
||||
let under = self.surface_under_and_global_space(pos);
|
||||
let under = self.niri.surface_under_and_global_space(pos);
|
||||
|
||||
pointer.motion(
|
||||
self,
|
||||
@@ -585,8 +584,8 @@ impl Niri {
|
||||
},
|
||||
);
|
||||
|
||||
let tablet_seat = self.seat.tablet_seat();
|
||||
let tool = tablet_seat.add_tool::<Self>(&self.display_handle, &event.tool());
|
||||
let tablet_seat = self.niri.seat.tablet_seat();
|
||||
let tool = tablet_seat.add_tool::<Self>(&self.niri.display_handle, &event.tool());
|
||||
let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&event.device()));
|
||||
if let (Some(under), Some(tablet)) = (under, tablet) {
|
||||
match event.state() {
|
||||
@@ -602,7 +601,7 @@ impl Niri {
|
||||
}
|
||||
}
|
||||
InputEvent::TabletToolButton { event, .. } => {
|
||||
let tool = self.seat.tablet_seat().get_tool(&event.tool());
|
||||
let tool = self.niri.seat.tablet_seat().get_tool(&event.tool());
|
||||
|
||||
if let Some(tool) = tool {
|
||||
tool.button(
|
||||
@@ -615,14 +614,15 @@ impl Niri {
|
||||
}
|
||||
InputEvent::DeviceAdded { device } => {
|
||||
if device.has_capability(DeviceCapability::TabletTool) {
|
||||
self.seat
|
||||
.tablet_seat()
|
||||
.add_tablet::<Self>(&self.display_handle, &TabletDescriptor::from(&device));
|
||||
self.niri.seat.tablet_seat().add_tablet::<Self>(
|
||||
&self.niri.display_handle,
|
||||
&TabletDescriptor::from(&device),
|
||||
);
|
||||
}
|
||||
}
|
||||
InputEvent::DeviceRemoved { device } => {
|
||||
if device.has_capability(DeviceCapability::TabletTool) {
|
||||
let tablet_seat = self.seat.tablet_seat();
|
||||
let tablet_seat = self.niri.seat.tablet_seat();
|
||||
|
||||
tablet_seat.remove_tablet(&TabletDescriptor::from(&device));
|
||||
|
||||
@@ -634,7 +634,7 @@ impl Niri {
|
||||
}
|
||||
InputEvent::GestureSwipeBegin { event } => {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
pointer.gesture_swipe_begin(
|
||||
self,
|
||||
&GestureSwipeBeginEvent {
|
||||
@@ -645,7 +645,7 @@ impl Niri {
|
||||
);
|
||||
}
|
||||
InputEvent::GestureSwipeUpdate { event } => {
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
pointer.gesture_swipe_update(
|
||||
self,
|
||||
&GestureSwipeUpdateEvent {
|
||||
@@ -656,7 +656,7 @@ impl Niri {
|
||||
}
|
||||
InputEvent::GestureSwipeEnd { event } => {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
pointer.gesture_swipe_end(
|
||||
self,
|
||||
&GestureSwipeEndEvent {
|
||||
@@ -668,7 +668,7 @@ impl Niri {
|
||||
}
|
||||
InputEvent::GesturePinchBegin { event } => {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
pointer.gesture_pinch_begin(
|
||||
self,
|
||||
&GesturePinchBeginEvent {
|
||||
@@ -679,7 +679,7 @@ impl Niri {
|
||||
);
|
||||
}
|
||||
InputEvent::GesturePinchUpdate { event } => {
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
pointer.gesture_pinch_update(
|
||||
self,
|
||||
&GesturePinchUpdateEvent {
|
||||
@@ -694,7 +694,7 @@ impl Niri {
|
||||
}
|
||||
InputEvent::GesturePinchEnd { event } => {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
pointer.gesture_pinch_end(
|
||||
self,
|
||||
&GesturePinchEndEvent {
|
||||
@@ -706,7 +706,7 @@ impl Niri {
|
||||
}
|
||||
InputEvent::GestureHoldBegin { event } => {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
pointer.gesture_hold_begin(
|
||||
self,
|
||||
&GestureHoldBeginEvent {
|
||||
@@ -718,7 +718,7 @@ impl Niri {
|
||||
}
|
||||
InputEvent::GestureHoldEnd { event } => {
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
let pointer = self.seat.get_pointer().unwrap();
|
||||
let pointer = self.niri.seat.get_pointer().unwrap();
|
||||
pointer.gesture_hold_end(
|
||||
self,
|
||||
&GestureHoldEndEvent {
|
||||
@@ -735,8 +735,6 @@ impl Niri {
|
||||
InputEvent::TouchFrame { .. } => (),
|
||||
InputEvent::Special(_) => (),
|
||||
}
|
||||
|
||||
BackendAction::None
|
||||
}
|
||||
|
||||
pub fn process_libinput_event(&mut self, event: &mut InputEvent<LibinputInputBackend>) {
|
||||
|
||||
+13
-5
@@ -16,8 +16,9 @@ use std::env;
|
||||
use std::ffi::OsString;
|
||||
|
||||
use clap::Parser;
|
||||
use niri::{Data, Niri};
|
||||
use niri::{Niri, State};
|
||||
use smithay::reexports::calloop::EventLoop;
|
||||
use smithay::reexports::wayland_server::Display;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
#[derive(Parser)]
|
||||
@@ -28,6 +29,11 @@ struct Cli {
|
||||
command: Vec<OsString>,
|
||||
}
|
||||
|
||||
struct LoopData {
|
||||
display: Display<State>,
|
||||
state: State,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
|
||||
@@ -43,7 +49,9 @@ fn main() {
|
||||
let _client = tracy_client::Client::start();
|
||||
|
||||
let mut event_loop = EventLoop::try_new().unwrap();
|
||||
let mut data = Data::new(event_loop.handle(), event_loop.get_signal());
|
||||
let mut display = Display::new().unwrap();
|
||||
let state = State::new(event_loop.handle(), event_loop.get_signal(), &mut display);
|
||||
let mut data = LoopData { display, state };
|
||||
|
||||
if let Some((command, args)) = cli.command.split_first() {
|
||||
if let Err(err) = std::process::Command::new(command).args(args).spawn() {
|
||||
@@ -56,9 +64,9 @@ fn main() {
|
||||
let _span = tracy_client::span!("loop callback");
|
||||
|
||||
// These should be called periodically, before flushing the clients.
|
||||
data.niri.monitor_set.refresh();
|
||||
data.niri.popups.cleanup();
|
||||
data.niri.update_focus();
|
||||
data.state.niri.monitor_set.refresh();
|
||||
data.state.niri.popups.cleanup();
|
||||
data.state.update_focus();
|
||||
|
||||
{
|
||||
let _span = tracy_client::span!("flush_clients");
|
||||
|
||||
+64
-62
@@ -58,10 +58,11 @@ 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 start_time: std::time::Instant,
|
||||
pub event_loop: LoopHandle<'static, Data>,
|
||||
pub event_loop: LoopHandle<'static, LoopData>,
|
||||
pub stop_signal: LoopSignal,
|
||||
pub display_handle: DisplayHandle,
|
||||
|
||||
@@ -84,14 +85,14 @@ pub struct Niri {
|
||||
pub layer_shell_state: WlrLayerShellState,
|
||||
pub shm_state: ShmState,
|
||||
pub output_manager_state: OutputManagerState,
|
||||
pub seat_state: SeatState<Self>,
|
||||
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<Self>,
|
||||
pub seat: Seat<State>,
|
||||
|
||||
pub pointer_buffer: Option<(TextureBuffer<GlesTexture>, Point<i32, Physical>)>,
|
||||
pub cursor_image: CursorImageStatus,
|
||||
@@ -112,14 +113,17 @@ pub struct OutputState {
|
||||
pub frame_clock: FrameClock,
|
||||
}
|
||||
|
||||
pub struct Data {
|
||||
pub display: Display<Niri>,
|
||||
pub struct State {
|
||||
pub backend: Backend,
|
||||
pub niri: Niri,
|
||||
}
|
||||
|
||||
impl Data {
|
||||
pub fn new(event_loop: LoopHandle<'static, Self>, stop_signal: LoopSignal) -> Self {
|
||||
impl State {
|
||||
pub fn new(
|
||||
event_loop: LoopHandle<'static, LoopData>,
|
||||
stop_signal: LoopSignal,
|
||||
display: &mut Display<State>,
|
||||
) -> Self {
|
||||
let has_display =
|
||||
env::var_os("WAYLAND_DISPLAY").is_some() || env::var_os("DISPLAY").is_some();
|
||||
|
||||
@@ -129,45 +133,76 @@ impl Data {
|
||||
Backend::Tty(Tty::new(event_loop.clone()))
|
||||
};
|
||||
|
||||
let mut display = Display::new().unwrap();
|
||||
let mut niri = Niri::new(event_loop, stop_signal, &mut display, backend.seat_name());
|
||||
let mut niri = Niri::new(event_loop, stop_signal, display, backend.seat_name());
|
||||
backend.init(&mut niri);
|
||||
|
||||
Self {
|
||||
display,
|
||||
backend,
|
||||
niri,
|
||||
Self { backend, niri }
|
||||
}
|
||||
|
||||
pub fn move_cursor(&mut self, location: Point<f64, Logical>) {
|
||||
let under = self.niri.surface_under_and_global_space(location);
|
||||
self.niri.seat.get_pointer().unwrap().motion(
|
||||
self,
|
||||
under,
|
||||
&MotionEvent {
|
||||
location,
|
||||
serial: SERIAL_COUNTER.next_serial(),
|
||||
time: get_monotonic_time().as_millis() as u32,
|
||||
},
|
||||
);
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
|
||||
pub fn move_cursor_to_output(&mut self, output: &Output) {
|
||||
let geo = self.niri.global_space.output_geometry(output).unwrap();
|
||||
self.move_cursor(center(geo).to_f64());
|
||||
}
|
||||
|
||||
pub fn update_focus(&mut self) {
|
||||
let focus = self.niri.layer_surface_focus().or_else(|| {
|
||||
self.niri
|
||||
.monitor_set
|
||||
.focus()
|
||||
.map(|win| win.toplevel().wl_surface().clone())
|
||||
});
|
||||
let keyboard = self.niri.seat.get_keyboard().unwrap();
|
||||
if keyboard.current_focus() != focus {
|
||||
keyboard.set_focus(self, focus, SERIAL_COUNTER.next_serial());
|
||||
// FIXME: can be more granular.
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Niri {
|
||||
pub fn new(
|
||||
event_loop: LoopHandle<'static, Data>,
|
||||
event_loop: LoopHandle<'static, LoopData>,
|
||||
stop_signal: LoopSignal,
|
||||
display: &mut Display<Self>,
|
||||
display: &mut Display<State>,
|
||||
seat_name: String,
|
||||
) -> Self {
|
||||
let start_time = std::time::Instant::now();
|
||||
|
||||
let display_handle = display.handle();
|
||||
|
||||
let compositor_state = CompositorState::new::<Self>(&display_handle);
|
||||
let xdg_shell_state = XdgShellState::new_with_capabilities::<Self>(
|
||||
let compositor_state = CompositorState::new::<State>(&display_handle);
|
||||
let xdg_shell_state = XdgShellState::new_with_capabilities::<State>(
|
||||
&display_handle,
|
||||
[WmCapabilities::Fullscreen],
|
||||
);
|
||||
let layer_shell_state = WlrLayerShellState::new::<Self>(&display_handle);
|
||||
let shm_state = ShmState::new::<Self>(&display_handle, vec![]);
|
||||
let output_manager_state = OutputManagerState::new_with_xdg_output::<Self>(&display_handle);
|
||||
let layer_shell_state = WlrLayerShellState::new::<State>(&display_handle);
|
||||
let shm_state = ShmState::new::<State>(&display_handle, vec![]);
|
||||
let output_manager_state =
|
||||
OutputManagerState::new_with_xdg_output::<State>(&display_handle);
|
||||
let mut seat_state = SeatState::new();
|
||||
let tablet_state = TabletManagerState::new::<Self>(&display_handle);
|
||||
let pointer_gestures_state = PointerGesturesState::new::<Self>(&display_handle);
|
||||
let data_device_state = DataDeviceState::new::<Self>(&display_handle);
|
||||
let tablet_state = TabletManagerState::new::<State>(&display_handle);
|
||||
let pointer_gestures_state = PointerGesturesState::new::<State>(&display_handle);
|
||||
let data_device_state = DataDeviceState::new::<State>(&display_handle);
|
||||
let presentation_state =
|
||||
PresentationState::new::<Self>(&display_handle, CLOCK_MONOTONIC as u32);
|
||||
PresentationState::new::<State>(&display_handle, CLOCK_MONOTONIC as u32);
|
||||
|
||||
let mut seat: Seat<Self> = seat_state.new_wl_seat(&display_handle, seat_name);
|
||||
let mut seat: Seat<State> = seat_state.new_wl_seat(&display_handle, seat_name);
|
||||
// FIXME: get Xkb and repeat interval from GNOME dconf.
|
||||
let xkb = XkbConfig {
|
||||
layout: "us,ru",
|
||||
@@ -182,6 +217,7 @@ impl Niri {
|
||||
event_loop
|
||||
.insert_source(socket_source, move |client, _, data| {
|
||||
if let Err(err) = data
|
||||
.state
|
||||
.niri
|
||||
.display_handle
|
||||
.insert_client(client, Arc::new(ClientState::default()))
|
||||
@@ -280,7 +316,7 @@ impl Niri {
|
||||
);
|
||||
event_loop
|
||||
.insert_source(display_source, |_, _, data| {
|
||||
data.display.dispatch_clients(&mut data.niri).unwrap();
|
||||
data.display.dispatch_clients(&mut data.state).unwrap();
|
||||
Ok(PostAction::Continue)
|
||||
})
|
||||
.unwrap();
|
||||
@@ -331,7 +367,7 @@ impl Niri {
|
||||
self.monitor_set.add_output(output.clone());
|
||||
|
||||
let state = OutputState {
|
||||
global: output.create_global::<Niri>(&self.display_handle),
|
||||
global: output.create_global::<State>(&self.display_handle),
|
||||
queued_redraw: None,
|
||||
waiting_for_vblank: false,
|
||||
frame_clock: FrameClock::new(refresh_interval),
|
||||
@@ -477,26 +513,6 @@ impl Niri {
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn move_cursor(&mut self, location: Point<f64, Logical>) {
|
||||
let under = self.surface_under_and_global_space(location);
|
||||
self.seat.get_pointer().unwrap().motion(
|
||||
self,
|
||||
under,
|
||||
&MotionEvent {
|
||||
location,
|
||||
serial: SERIAL_COUNTER.next_serial(),
|
||||
time: get_monotonic_time().as_millis() as u32,
|
||||
},
|
||||
);
|
||||
// FIXME: granular
|
||||
self.queue_redraw_all();
|
||||
}
|
||||
|
||||
pub fn move_cursor_to_output(&mut self, output: &Output) {
|
||||
let geo = self.global_space.output_geometry(output).unwrap();
|
||||
self.move_cursor(center(geo).to_f64());
|
||||
}
|
||||
|
||||
fn layer_surface_focus(&self) -> Option<WlSurface> {
|
||||
let output = self.monitor_set.active_output()?;
|
||||
let layers = layer_map_for_output(output);
|
||||
@@ -508,20 +524,6 @@ impl Niri {
|
||||
Some(surface.wl_surface().clone())
|
||||
}
|
||||
|
||||
pub fn update_focus(&mut self) {
|
||||
let focus = self.layer_surface_focus().or_else(|| {
|
||||
self.monitor_set
|
||||
.focus()
|
||||
.map(|win| win.toplevel().wl_surface().clone())
|
||||
});
|
||||
let keyboard = self.seat.get_keyboard().unwrap();
|
||||
if keyboard.current_focus() != focus {
|
||||
keyboard.set_focus(self, focus, SERIAL_COUNTER.next_serial());
|
||||
// FIXME: can be more granular.
|
||||
self.queue_redraw_all();
|
||||
}
|
||||
}
|
||||
|
||||
/// Schedules an immediate redraw on all outputs if one is not already scheduled.
|
||||
pub fn queue_redraw_all(&mut self) {
|
||||
let outputs: Vec<_> = self.output_state.keys().cloned().collect();
|
||||
@@ -541,7 +543,7 @@ impl Niri {
|
||||
// Timer::immediate() adds a millisecond of delay for some reason.
|
||||
// This should be fixed in calloop v0.11: https://github.com/Smithay/calloop/issues/142
|
||||
let idle = self.event_loop.insert_idle(move |data| {
|
||||
data.niri.redraw(&mut data.backend, &output);
|
||||
data.state.niri.redraw(&mut data.state.backend, &output);
|
||||
});
|
||||
state.queued_redraw = Some(idle);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user