aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2023-10-26 00:15:46 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-10-29 13:58:48 +0400
commit0a2052945e62c31585a3c7ec4c0efa84ebc5d312 (patch)
treea339cae5e7ba362d7adf18c62948eb009a368d24 /src
parent49a8f156f34434977358ea9f0a9cb97a753d857f (diff)
downloadniri-0a2052945e62c31585a3c7ec4c0efa84ebc5d312.tar.gz
niri-0a2052945e62c31585a3c7ec4c0efa84ebc5d312.tar.bz2
niri-0a2052945e62c31585a3c7ec4c0efa84ebc5d312.zip
Add support for wl_compositor@v6
Diffstat (limited to 'src')
-rw-r--r--src/backend/tty.rs5
-rw-r--r--src/backend/winit.rs13
-rw-r--r--src/handlers/compositor.rs15
-rw-r--r--src/handlers/layer_shell.rs8
-rw-r--r--src/handlers/mod.rs18
-rw-r--r--src/handlers/xdg_shell.rs16
-rw-r--r--src/layout.rs22
-rw-r--r--src/niri.rs29
8 files changed, 105 insertions, 21 deletions
diff --git a/src/backend/tty.rs b/src/backend/tty.rs
index 52ec1ebd..1c3bbe44 100644
--- a/src/backend/tty.rs
+++ b/src/backend/tty.rs
@@ -529,9 +529,6 @@ impl Tty {
.map(|info| (info.manufacturer, info.model))
.unwrap_or_else(|| ("Unknown".into(), "Unknown".into()));
- let scale = config.scale.clamp(0.1, 10.);
- let scale = scale.max(1.).round() as i32;
-
let output = Output::new(
output_name.clone(),
PhysicalProperties {
@@ -541,7 +538,9 @@ impl Tty {
make,
},
);
+
let wl_mode = Mode::from(*mode);
+ let scale = config.scale.clamp(1., 10.).ceil() as i32;
output.change_current_state(Some(wl_mode), None, Some(Scale::Integer(scale)), None);
output.set_preferred(wl_mode);
diff --git a/src/backend/winit.rs b/src/backend/winit.rs
index 1afb8d97..9bdf734b 100644
--- a/src/backend/winit.rs
+++ b/src/backend/winit.rs
@@ -45,13 +45,6 @@ impl Winit {
.find(|o| o.name == "winit")
.cloned()
.unwrap_or_default();
- let scale = output_config.scale.clamp(0.1, 10.);
- let scale = scale.max(1.).round() as i32;
-
- let mode = Mode {
- size: backend.window_size(),
- refresh: 60_000,
- };
let output = Output::new(
"winit".to_string(),
@@ -62,6 +55,12 @@ impl Winit {
model: "Winit".into(),
},
);
+
+ let mode = Mode {
+ size: backend.window_size(),
+ refresh: 60_000,
+ };
+ let scale = output_config.scale.clamp(1., 10.).ceil() as i32;
output.change_current_state(
Some(mode),
Some(Transform::Flipped180),
diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs
index 034f1ca5..71696d06 100644
--- a/src/handlers/compositor.rs
+++ b/src/handlers/compositor.rs
@@ -9,8 +9,9 @@ use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::reexports::wayland_server::{Client, Resource};
use smithay::wayland::buffer::BufferHandler;
use smithay::wayland::compositor::{
- add_blocker, add_pre_commit_hook, get_parent, is_sync_subsurface, with_states,
- BufferAssignment, CompositorClientState, CompositorHandler, CompositorState, SurfaceAttributes,
+ add_blocker, add_pre_commit_hook, get_parent, is_sync_subsurface, send_surface_state,
+ with_states, BufferAssignment, CompositorClientState, CompositorHandler, CompositorState,
+ SurfaceAttributes,
};
use smithay::wayland::dmabuf::get_dmabuf;
use smithay::wayland::shm::{ShmHandler, ShmState};
@@ -28,6 +29,16 @@ impl CompositorHandler for State {
&client.get_data::<ClientState>().unwrap().compositor_state
}
+ fn new_subsurface(&mut self, surface: &WlSurface, parent: &WlSurface) {
+ if let Some((_, output)) = self.niri.layout.find_window_and_output(parent) {
+ let scale = output.current_scale().integer_scale();
+ let transform = output.current_transform();
+ with_states(surface, |data| {
+ send_surface_state(surface, data, scale, transform);
+ });
+ }
+ }
+
fn new_surface(&mut self, surface: &WlSurface) {
add_pre_commit_hook::<Self, _>(surface, move |state, _dh, surface| {
let maybe_dmabuf = with_states(surface, |surface_data| {
diff --git a/src/handlers/layer_shell.rs b/src/handlers/layer_shell.rs
index 6e0ef318..a5b1d120 100644
--- a/src/handlers/layer_shell.rs
+++ b/src/handlers/layer_shell.rs
@@ -3,7 +3,7 @@ use smithay::desktop::{layer_map_for_output, LayerSurface, WindowSurfaceType};
use smithay::output::Output;
use smithay::reexports::wayland_server::protocol::wl_output::WlOutput;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
-use smithay::wayland::compositor::with_states;
+use smithay::wayland::compositor::{send_surface_state, with_states};
use smithay::wayland::shell::wlr_layer::{
Layer, LayerSurface as WlrLayerSurface, LayerSurfaceData, WlrLayerShellHandler,
WlrLayerShellState,
@@ -92,6 +92,12 @@ impl State {
.layer_for_surface(surface, WindowSurfaceType::TOPLEVEL)
.unwrap();
+ let scale = output.current_scale().integer_scale();
+ let transform = output.current_transform();
+ with_states(surface, |data| {
+ send_surface_state(surface, data, scale, transform);
+ });
+
layer.layer_surface().send_configure();
}
drop(map);
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs
index 19742fcc..85e9e755 100644
--- a/src/handlers/mod.rs
+++ b/src/handlers/mod.rs
@@ -19,6 +19,7 @@ use smithay::reexports::wayland_server::protocol::wl_output::WlOutput;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::reexports::wayland_server::Resource;
use smithay::utils::{Logical, Rectangle, Size};
+use smithay::wayland::compositor::{send_surface_state, with_states};
use smithay::wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportError};
use smithay::wayland::input_method::{InputMethodHandler, PopupSurface};
use smithay::wayland::selection::data_device::{
@@ -71,6 +72,17 @@ delegate_text_input_manager!(State);
impl InputMethodHandler for State {
fn new_popup(&mut self, surface: PopupSurface) {
+ if let Some((_, output)) = surface
+ .get_parent()
+ .and_then(|parent| self.niri.layout.find_window_and_output(&parent.surface))
+ {
+ let scale = output.current_scale().integer_scale();
+ let transform = output.current_transform();
+ let wl_surface = surface.wl_surface();
+ with_states(wl_surface, |data| {
+ send_surface_state(wl_surface, data, scale, transform);
+ });
+ }
if let Err(err) = self.niri.popups.track_popup(PopupKind::from(surface)) {
warn!("error tracking ime popup {err:?}");
}
@@ -216,5 +228,11 @@ pub fn configure_lock_surface(surface: &LockSurface, output: &Output) {
let size = output_size(output);
states.size = Some(Size::from((size.w as u32, size.h as u32)));
});
+ let scale = output.current_scale().integer_scale();
+ let transform = output.current_transform();
+ let wl_surface = surface.wl_surface();
+ with_states(wl_surface, |data| {
+ send_surface_state(wl_surface, data, scale, transform);
+ });
surface.send_configure();
}
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs
index d0532a3b..d99fbdf0 100644
--- a/src/handlers/xdg_shell.rs
+++ b/src/handlers/xdg_shell.rs
@@ -6,7 +6,7 @@ use smithay::reexports::wayland_server::protocol::wl_output;
use smithay::reexports::wayland_server::protocol::wl_seat::WlSeat;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::utils::Serial;
-use smithay::wayland::compositor::with_states;
+use smithay::wayland::compositor::{send_surface_state, with_states};
use smithay::wayland::shell::kde::decoration::{KdeDecorationHandler, KdeDecorationState};
use smithay::wayland::shell::xdg::decoration::XdgDecorationHandler;
use smithay::wayland::shell::xdg::{
@@ -264,8 +264,18 @@ impl State {
.initial_configure_sent
});
if !initial_configure_sent {
- // NOTE: This should never fail as the initial configure is always
- // allowed.
+ if let Some(output) = popup.get_parent_surface().and_then(|parent| {
+ self.niri
+ .layout
+ .find_window_and_output(&parent)
+ .map(|(_, output)| output)
+ }) {
+ let scale = output.current_scale().integer_scale();
+ let transform = output.current_transform();
+ with_states(surface, |data| {
+ send_surface_state(surface, data, scale, transform);
+ });
+ }
popup.send_configure().expect("initial configure failed");
}
}
diff --git a/src/layout.rs b/src/layout.rs
index 5c4a633e..ebfe0c1e 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -52,7 +52,7 @@ use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::render_elements;
use smithay::utils::{Logical, Point, Rectangle, Scale, Size};
-use smithay::wayland::compositor::with_states;
+use smithay::wayland::compositor::{send_surface_state, with_states, SurfaceData};
use smithay::wayland::shell::xdg::SurfaceCachedState;
use crate::animation::Animation;
@@ -77,6 +77,7 @@ pub trait LayoutElement: SpaceElement + PartialEq + Clone {
fn max_size(&self) -> Size<i32, Logical>;
fn is_wl_surface(&self, wl_surface: &WlSurface) -> bool;
fn has_ssd(&self) -> bool;
+ fn with_surfaces<F: FnMut(&WlSurface, &SurfaceData)>(&self, processor: F);
}
#[derive(Debug)]
@@ -333,6 +334,10 @@ impl LayoutElement for Window {
self.toplevel().wl_surface() == wl_surface
}
+ fn with_surfaces<F: FnMut(&WlSurface, &SurfaceData)>(&self, processor: F) {
+ self.with_surfaces(processor);
+ }
+
fn has_ssd(&self) -> bool {
self.toplevel().current_state().decoration_mode
== Some(zxdg_toplevel_decoration_v1::Mode::ServerSide)
@@ -1903,6 +1908,7 @@ impl<W: LayoutElement> Workspace<W> {
fn enter_output_for_window(&self, window: &W) {
if let Some(output) = &self.output {
// FIXME: proper overlap.
+ self.send_surface_state_for_window_tree(window, output);
window.output_enter(
output,
Rectangle::from_loc_and_size((0, 0), (i32::MAX, i32::MAX)),
@@ -1937,12 +1943,24 @@ impl<W: LayoutElement> Workspace<W> {
let bounds = self.toplevel_bounds();
+ if let Some(output) = self.output.as_ref() {
+ self.send_surface_state_for_window_tree(window, output);
+ }
+
window.toplevel().with_pending_state(|state| {
state.size = Some(size);
state.bounds = Some(bounds);
});
}
+ fn send_surface_state_for_window_tree(&self, window: &impl LayoutElement, output: &Output) {
+ let scale = output.current_scale().integer_scale();
+ let transform = output.current_transform();
+ window.with_surfaces(|surface, data| {
+ send_surface_state(surface, data, scale, transform);
+ });
+ }
+
fn compute_new_view_offset_for_column(&self, current_x: i32, idx: usize) -> i32 {
if self.columns[idx].is_fullscreen {
return 0;
@@ -2890,6 +2908,8 @@ mod tests {
false
}
+ fn with_surfaces<F: FnMut(&WlSurface, &SurfaceData)>(&self, _processor: F) {}
+
fn has_ssd(&self) -> bool {
false
}
diff --git a/src/niri.rs b/src/niri.rs
index 91878e2e..db688266 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -49,8 +49,8 @@ use smithay::utils::{
SERIAL_COUNTER,
};
use smithay::wayland::compositor::{
- with_states, with_surface_tree_downward, CompositorClientState, CompositorState, SurfaceData,
- TraversalAction,
+ send_surface_state, with_states, with_surface_tree_downward, CompositorClientState,
+ CompositorState, SurfaceData, TraversalAction,
};
use smithay::wayland::dmabuf::DmabufFeedback;
use smithay::wayland::input_method::InputMethodManagerState;
@@ -511,7 +511,7 @@ impl Niri {
let layout = Layout::new(&config_);
- let compositor_state = CompositorState::new::<State>(&display_handle);
+ let compositor_state = CompositorState::new_v6::<State>(&display_handle);
let xdg_shell_state = XdgShellState::new_with_capabilities::<State>(
&display_handle,
[WmCapabilities::Fullscreen],
@@ -542,7 +542,7 @@ impl Niri {
|_| true,
);
let presentation_state =
- PresentationState::new::<State>(&display_handle, Monotonic::id() as u32);
+ PresentationState::new::<State>(&display_handle, Monotonic::ID as u32);
let text_input_state = TextInputManagerState::new::<State>(&display_handle);
let input_method_state =
@@ -1163,6 +1163,7 @@ impl Niri {
let pointer_pos = self.seat.get_pointer().unwrap().current_location();
+ let mut dnd_scale = 1;
for output in self.global_space.outputs() {
let geo = self.global_space.output_geometry(output).unwrap();
@@ -1180,10 +1181,15 @@ impl Niri {
if let Some(mut overlap) = geo.intersection(bbox) {
overlap.loc -= surface_pos;
+ dnd_scale = dnd_scale.max(output.current_scale().integer_scale());
output_update(output, Some(overlap), surface);
} else {
output_update(output, None, surface);
}
+
+ with_states(surface, |data| {
+ send_surface_state(surface, data, dnd_scale, Transform::Normal);
+ });
}
}
CursorImageStatus::Surface(surface) => {
@@ -1206,12 +1212,17 @@ impl Niri {
.as_ref()
.map(|surface| (surface, bbox_from_surface_tree(surface, surface_pos)));
+ // FIXME we basically need to pick the largest scale factor across the overlapping
+ // outputs, this is how it's usually done in clients as well.
+ let mut cursor_scale = 1;
+ let mut dnd_scale = 1;
for output in self.global_space.outputs() {
let geo = self.global_space.output_geometry(output).unwrap();
// Compute pointer surface overlap.
if let Some(mut overlap) = geo.intersection(bbox) {
overlap.loc -= surface_pos;
+ cursor_scale = cursor_scale.max(output.current_scale().integer_scale());
output_update(output, Some(overlap), surface);
} else {
output_update(output, None, surface);
@@ -1221,12 +1232,22 @@ impl Niri {
if let Some((surface, bbox)) = dnd {
if let Some(mut overlap) = geo.intersection(bbox) {
overlap.loc -= surface_pos;
+ dnd_scale = dnd_scale.max(output.current_scale().integer_scale());
output_update(output, Some(overlap), surface);
} else {
output_update(output, None, surface);
}
}
}
+
+ with_states(surface, |data| {
+ send_surface_state(surface, data, cursor_scale, Transform::Normal);
+ });
+ if let Some((surface, _)) = dnd {
+ with_states(surface, |data| {
+ send_surface_state(surface, data, dnd_scale, Transform::Normal);
+ });
+ }
}
}
}