mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
Wrap mapped windows in a Mapped
This commit is contained in:
+19
-16
@@ -17,8 +17,7 @@ use smithay::wayland::shm::{ShmHandler, ShmState};
|
|||||||
use smithay::{delegate_compositor, delegate_shm};
|
use smithay::{delegate_compositor, delegate_shm};
|
||||||
|
|
||||||
use crate::niri::{ClientState, State};
|
use crate::niri::{ClientState, State};
|
||||||
use crate::utils::clone2;
|
use crate::window::{InitialConfigureState, Mapped, ResolvedWindowRules, Unmapped};
|
||||||
use crate::window::{InitialConfigureState, Unmapped};
|
|
||||||
|
|
||||||
impl CompositorHandler for State {
|
impl CompositorHandler for State {
|
||||||
fn compositor_state(&mut self) -> &mut CompositorState {
|
fn compositor_state(&mut self) -> &mut CompositorState {
|
||||||
@@ -109,22 +108,22 @@ impl CompositorHandler for State {
|
|||||||
|
|
||||||
window.on_commit();
|
window.on_commit();
|
||||||
|
|
||||||
let (width, is_full_width, output) =
|
let (rules, width, is_full_width, output) =
|
||||||
if let InitialConfigureState::Configured {
|
if let InitialConfigureState::Configured {
|
||||||
|
rules,
|
||||||
width,
|
width,
|
||||||
is_full_width,
|
is_full_width,
|
||||||
output,
|
output,
|
||||||
..
|
|
||||||
} = state
|
} = state
|
||||||
{
|
{
|
||||||
// Check that the output is still connected.
|
// Check that the output is still connected.
|
||||||
let output =
|
let output =
|
||||||
output.filter(|o| self.niri.layout.monitor_for_output(o).is_some());
|
output.filter(|o| self.niri.layout.monitor_for_output(o).is_some());
|
||||||
|
|
||||||
(width, is_full_width, output)
|
(rules, width, is_full_width, output)
|
||||||
} else {
|
} else {
|
||||||
error!("window map must happen after initial configure");
|
error!("window map must happen after initial configure");
|
||||||
(None, false, None)
|
(ResolvedWindowRules::default(), None, false, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent = window
|
let parent = window
|
||||||
@@ -141,29 +140,30 @@ impl CompositorHandler for State {
|
|||||||
.filter(|(_, parent_output)| {
|
.filter(|(_, parent_output)| {
|
||||||
output.is_none() || output.as_ref() == Some(*parent_output)
|
output.is_none() || output.as_ref() == Some(*parent_output)
|
||||||
})
|
})
|
||||||
.map(|(window, _)| window.clone());
|
.map(|(mapped, _)| mapped.window.clone());
|
||||||
|
|
||||||
let window = window.clone();
|
let mapped = Mapped::new(window, rules);
|
||||||
let win = window.clone();
|
let window = mapped.window.clone();
|
||||||
|
|
||||||
let output = if let Some(p) = parent {
|
let output = if let Some(p) = parent {
|
||||||
// Open dialogs immediately to the right of their parent window.
|
// Open dialogs immediately to the right of their parent window.
|
||||||
self.niri
|
self.niri
|
||||||
.layout
|
.layout
|
||||||
.add_window_right_of(&p, win, width, is_full_width)
|
.add_window_right_of(&p, mapped, width, is_full_width)
|
||||||
} else if let Some(output) = &output {
|
} else if let Some(output) = &output {
|
||||||
self.niri
|
self.niri
|
||||||
.layout
|
.layout
|
||||||
.add_window_on_output(output, win, width, is_full_width);
|
.add_window_on_output(output, mapped, width, is_full_width);
|
||||||
Some(output)
|
Some(output)
|
||||||
} else {
|
} else {
|
||||||
self.niri.layout.add_window(win, width, is_full_width)
|
self.niri.layout.add_window(mapped, width, is_full_width)
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(output) = output.cloned() {
|
if let Some(output) = output.cloned() {
|
||||||
self.niri.layout.start_open_animation_for_window(&window);
|
self.niri.layout.start_open_animation_for_window(&window);
|
||||||
|
|
||||||
let new_active_window = self.niri.layout.active_window().map(|(w, _)| w);
|
let new_active_window =
|
||||||
|
self.niri.layout.active_window().map(|(m, _)| &m.window);
|
||||||
if new_active_window == Some(&window) {
|
if new_active_window == Some(&window) {
|
||||||
self.maybe_warp_cursor_to_focus();
|
self.maybe_warp_cursor_to_focus();
|
||||||
}
|
}
|
||||||
@@ -183,8 +183,9 @@ impl CompositorHandler for State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is a commit of a previously-mapped root or a non-toplevel root.
|
// This is a commit of a previously-mapped root or a non-toplevel root.
|
||||||
if let Some(win_out) = self.niri.layout.find_window_and_output(surface) {
|
if let Some((mapped, output)) = self.niri.layout.find_window_and_output(surface) {
|
||||||
let (window, output) = clone2(win_out);
|
let window = mapped.window.clone();
|
||||||
|
let output = output.clone();
|
||||||
|
|
||||||
window.on_commit();
|
window.on_commit();
|
||||||
|
|
||||||
@@ -224,7 +225,9 @@ impl CompositorHandler for State {
|
|||||||
|
|
||||||
// This is a commit of a non-root or a non-toplevel root.
|
// This is a commit of a non-root or a non-toplevel root.
|
||||||
let root_window_output = self.niri.layout.find_window_and_output(&root_surface);
|
let root_window_output = self.niri.layout.find_window_and_output(&root_surface);
|
||||||
if let Some((window, output)) = root_window_output.map(clone2) {
|
if let Some((mapped, output)) = root_window_output {
|
||||||
|
let window = mapped.window.clone();
|
||||||
|
let output = output.clone();
|
||||||
window.on_commit();
|
window.on_commit();
|
||||||
self.niri.layout.update_window(&window);
|
self.niri.layout.update_window(&window);
|
||||||
self.niri.queue_redraw(output);
|
self.niri.queue_redraw(output);
|
||||||
|
|||||||
+10
-11
@@ -144,7 +144,7 @@ impl InputMethodHandler for State {
|
|||||||
self.niri
|
self.niri
|
||||||
.layout
|
.layout
|
||||||
.find_window_and_output(parent)
|
.find_window_and_output(parent)
|
||||||
.map(|(window, _)| window.geometry())
|
.map(|(mapped, _)| mapped.window.geometry())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,25 +333,24 @@ impl ForeignToplevelHandler for State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn activate(&mut self, wl_surface: WlSurface) {
|
fn activate(&mut self, wl_surface: WlSurface) {
|
||||||
if let Some((window, _)) = self.niri.layout.find_window_and_output(&wl_surface) {
|
if let Some((mapped, _)) = self.niri.layout.find_window_and_output(&wl_surface) {
|
||||||
let window = window.clone();
|
let window = mapped.window.clone();
|
||||||
self.niri.layout.activate_window(&window);
|
self.niri.layout.activate_window(&window);
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(&mut self, wl_surface: WlSurface) {
|
fn close(&mut self, wl_surface: WlSurface) {
|
||||||
if let Some((window, _)) = self.niri.layout.find_window_and_output(&wl_surface) {
|
if let Some((mapped, _)) = self.niri.layout.find_window_and_output(&wl_surface) {
|
||||||
window.toplevel().expect("no x11 support").send_close();
|
mapped.toplevel().send_close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_fullscreen(&mut self, wl_surface: WlSurface, wl_output: Option<WlOutput>) {
|
fn set_fullscreen(&mut self, wl_surface: WlSurface, wl_output: Option<WlOutput>) {
|
||||||
if let Some((window, current_output)) = self.niri.layout.find_window_and_output(&wl_surface)
|
if let Some((mapped, current_output)) = self.niri.layout.find_window_and_output(&wl_surface)
|
||||||
{
|
{
|
||||||
if !window
|
if !mapped
|
||||||
.toplevel()
|
.toplevel()
|
||||||
.expect("no x11 support")
|
|
||||||
.current_state()
|
.current_state()
|
||||||
.capabilities
|
.capabilities
|
||||||
.contains(xdg_toplevel::WmCapabilities::Fullscreen)
|
.contains(xdg_toplevel::WmCapabilities::Fullscreen)
|
||||||
@@ -359,7 +358,7 @@ impl ForeignToplevelHandler for State {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let window = window.clone();
|
let window = mapped.window.clone();
|
||||||
|
|
||||||
if let Some(requested_output) = wl_output.as_ref().and_then(Output::from_resource) {
|
if let Some(requested_output) = wl_output.as_ref().and_then(Output::from_resource) {
|
||||||
if &requested_output != current_output {
|
if &requested_output != current_output {
|
||||||
@@ -374,8 +373,8 @@ impl ForeignToplevelHandler for State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn unset_fullscreen(&mut self, wl_surface: WlSurface) {
|
fn unset_fullscreen(&mut self, wl_surface: WlSurface) {
|
||||||
if let Some((window, _)) = self.niri.layout.find_window_and_output(&wl_surface) {
|
if let Some((mapped, _)) = self.niri.layout.find_window_and_output(&wl_surface) {
|
||||||
let window = window.clone();
|
let window = mapped.window.clone();
|
||||||
self.niri.layout.set_fullscreen(&window, false);
|
self.niri.layout.set_fullscreen(&window, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -29,7 +29,6 @@ use smithay::{
|
|||||||
|
|
||||||
use crate::layout::workspace::ColumnWidth;
|
use crate::layout::workspace::ColumnWidth;
|
||||||
use crate::niri::{PopupGrabState, State};
|
use crate::niri::{PopupGrabState, State};
|
||||||
use crate::utils::clone2;
|
|
||||||
use crate::window::{InitialConfigureState, ResolvedWindowRules, Unmapped};
|
use crate::window::{InitialConfigureState, ResolvedWindowRules, Unmapped};
|
||||||
|
|
||||||
fn window_matches(role: &XdgToplevelSurfaceRoleAttributes, m: &Match) -> bool {
|
fn window_matches(role: &XdgToplevelSurfaceRoleAttributes, m: &Match) -> bool {
|
||||||
@@ -213,9 +212,7 @@ impl XdgShellHandler for State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let layout_focus = self.niri.layout.focus();
|
let layout_focus = self.niri.layout.focus();
|
||||||
if Some(&root)
|
if Some(&root) != layout_focus.map(|win| win.toplevel().wl_surface()) {
|
||||||
!= layout_focus.map(|win| win.toplevel().expect("no x11 support").wl_surface())
|
|
||||||
{
|
|
||||||
let _ = PopupManager::dismiss_popup(&root, &popup);
|
let _ = PopupManager::dismiss_popup(&root, &popup);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -278,12 +275,12 @@ impl XdgShellHandler for State {
|
|||||||
) {
|
) {
|
||||||
let requested_output = wl_output.as_ref().and_then(Output::from_resource);
|
let requested_output = wl_output.as_ref().and_then(Output::from_resource);
|
||||||
|
|
||||||
if let Some((window, current_output)) = self
|
if let Some((mapped, current_output)) = self
|
||||||
.niri
|
.niri
|
||||||
.layout
|
.layout
|
||||||
.find_window_and_output(toplevel.wl_surface())
|
.find_window_and_output(toplevel.wl_surface())
|
||||||
{
|
{
|
||||||
let window = window.clone();
|
let window = mapped.window.clone();
|
||||||
|
|
||||||
if let Some(requested_output) = requested_output {
|
if let Some(requested_output) = requested_output {
|
||||||
if &requested_output != current_output {
|
if &requested_output != current_output {
|
||||||
@@ -358,12 +355,12 @@ impl XdgShellHandler for State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn unfullscreen_request(&mut self, toplevel: ToplevelSurface) {
|
fn unfullscreen_request(&mut self, toplevel: ToplevelSurface) {
|
||||||
if let Some((window, _)) = self
|
if let Some((mapped, _)) = self
|
||||||
.niri
|
.niri
|
||||||
.layout
|
.layout
|
||||||
.find_window_and_output(toplevel.wl_surface())
|
.find_window_and_output(toplevel.wl_surface())
|
||||||
{
|
{
|
||||||
let window = window.clone();
|
let window = mapped.window.clone();
|
||||||
self.niri.layout.set_fullscreen(&window, false);
|
self.niri.layout.set_fullscreen(&window, false);
|
||||||
|
|
||||||
// A configure is required in response to this event regardless if there are pending
|
// A configure is required in response to this event regardless if there are pending
|
||||||
@@ -453,14 +450,16 @@ impl XdgShellHandler for State {
|
|||||||
.layout
|
.layout
|
||||||
.find_window_and_output(surface.wl_surface());
|
.find_window_and_output(surface.wl_surface());
|
||||||
|
|
||||||
let Some((window, output)) = win_out.map(clone2) else {
|
let Some((mapped, output)) = win_out else {
|
||||||
// I have no idea how this can happen, but I saw it happen once, in a weird interaction
|
// I have no idea how this can happen, but I saw it happen once, in a weird interaction
|
||||||
// involving laptop going to sleep and resuming.
|
// involving laptop going to sleep and resuming.
|
||||||
error!("toplevel missing from both unmapped_windows and layout");
|
error!("toplevel missing from both unmapped_windows and layout");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let window = mapped.window.clone();
|
||||||
|
let output = output.clone();
|
||||||
|
|
||||||
let active_window = self.niri.layout.active_window().map(|(w, _)| w);
|
let active_window = self.niri.layout.active_window().map(|(m, _)| &m.window);
|
||||||
let was_active = active_window == Some(&window);
|
let was_active = active_window == Some(&window);
|
||||||
|
|
||||||
self.niri.layout.remove_window(&window);
|
self.niri.layout.remove_window(&window);
|
||||||
@@ -733,8 +732,8 @@ impl State {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Figure out if the root is a window or a layer surface.
|
// Figure out if the root is a window or a layer surface.
|
||||||
if let Some((window, output)) = self.niri.layout.find_window_and_output(&root) {
|
if let Some((mapped, output)) = self.niri.layout.find_window_and_output(&root) {
|
||||||
self.unconstrain_window_popup(popup, window, output);
|
self.unconstrain_window_popup(popup, &mapped.window, output);
|
||||||
} else if let Some((layer_surface, output)) = self.niri.layout.outputs().find_map(|o| {
|
} else if let Some((layer_surface, output)) = self.niri.layout.outputs().find_map(|o| {
|
||||||
let map = layer_map_for_output(o);
|
let map = layer_map_for_output(o);
|
||||||
let layer_surface = map.layer_for_surface(&root, WindowSurfaceType::TOPLEVEL)?;
|
let layer_surface = map.layer_for_surface(&root, WindowSurfaceType::TOPLEVEL)?;
|
||||||
@@ -814,6 +813,8 @@ impl State {
|
|||||||
if let InitialConfigureState::Configured { rules, .. } = &mut unmapped.state {
|
if let InitialConfigureState::Configured { rules, .. } = &mut unmapped.state {
|
||||||
*rules = resolve();
|
*rules = resolve();
|
||||||
}
|
}
|
||||||
|
} else if let Some(mapped) = self.niri.layout.find_window_mut(toplevel.wl_surface()) {
|
||||||
|
mapped.rules = resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-11
@@ -379,21 +379,24 @@ impl State {
|
|||||||
}
|
}
|
||||||
Action::ScreenshotWindow => {
|
Action::ScreenshotWindow => {
|
||||||
let active = self.niri.layout.active_window();
|
let active = self.niri.layout.active_window();
|
||||||
if let Some((window, output)) = active {
|
if let Some((mapped, output)) = active {
|
||||||
self.backend.with_primary_renderer(|renderer| {
|
self.backend.with_primary_renderer(|renderer| {
|
||||||
if let Err(err) = self.niri.screenshot_window(renderer, output, window) {
|
if let Err(err) =
|
||||||
|
self.niri
|
||||||
|
.screenshot_window(renderer, output, &mapped.window)
|
||||||
|
{
|
||||||
warn!("error taking screenshot: {err:?}");
|
warn!("error taking screenshot: {err:?}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Action::CloseWindow => {
|
Action::CloseWindow => {
|
||||||
if let Some(window) = self.niri.layout.focus() {
|
if let Some(mapped) = self.niri.layout.focus() {
|
||||||
window.toplevel().expect("no x11 support").send_close();
|
mapped.toplevel().send_close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Action::FullscreenWindow => {
|
Action::FullscreenWindow => {
|
||||||
let focus = self.niri.layout.focus().cloned();
|
let focus = self.niri.layout.focus().map(|m| m.window.clone());
|
||||||
if let Some(window) = focus {
|
if let Some(window) = focus {
|
||||||
self.niri.layout.toggle_fullscreen(&window);
|
self.niri.layout.toggle_fullscreen(&window);
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
@@ -1017,8 +1020,8 @@ impl State {
|
|||||||
let button_state = event.state();
|
let button_state = event.state();
|
||||||
|
|
||||||
if ButtonState::Pressed == button_state {
|
if ButtonState::Pressed == button_state {
|
||||||
if let Some(window) = self.niri.window_under_cursor() {
|
if let Some(mapped) = self.niri.window_under_cursor() {
|
||||||
let window = window.clone();
|
let window = mapped.window.clone();
|
||||||
self.niri.layout.activate_window(&window);
|
self.niri.layout.activate_window(&window);
|
||||||
|
|
||||||
// FIXME: granular.
|
// FIXME: granular.
|
||||||
@@ -1177,8 +1180,8 @@ impl State {
|
|||||||
tool.tip_down(serial, event.time_msec());
|
tool.tip_down(serial, event.time_msec());
|
||||||
|
|
||||||
if let Some(pos) = self.niri.tablet_cursor_location {
|
if let Some(pos) = self.niri.tablet_cursor_location {
|
||||||
if let Some(window) = self.niri.window_under(pos) {
|
if let Some(mapped) = self.niri.window_under(pos) {
|
||||||
let window = window.clone();
|
let window = mapped.window.clone();
|
||||||
self.niri.layout.activate_window(&window);
|
self.niri.layout.activate_window(&window);
|
||||||
|
|
||||||
// FIXME: granular.
|
// FIXME: granular.
|
||||||
@@ -1535,8 +1538,8 @@ impl State {
|
|||||||
.output_under(touch_location)
|
.output_under(touch_location)
|
||||||
.next()
|
.next()
|
||||||
.cloned();
|
.cloned();
|
||||||
if let Some(window) = self.niri.window_under(touch_location) {
|
if let Some(mapped) = self.niri.window_under(touch_location) {
|
||||||
let window = window.clone();
|
let window = mapped.window.clone();
|
||||||
self.niri.layout.activate_window(&window);
|
self.niri.layout.activate_window(&window);
|
||||||
|
|
||||||
// FIXME: granular.
|
// FIXME: granular.
|
||||||
|
|||||||
+26
-151
@@ -38,21 +38,14 @@ use niri_config::{CenterFocusedColumn, Config, Struts};
|
|||||||
use niri_ipc::SizeChange;
|
use niri_ipc::SizeChange;
|
||||||
use smithay::backend::renderer::element::solid::SolidColorRenderElement;
|
use smithay::backend::renderer::element::solid::SolidColorRenderElement;
|
||||||
use smithay::backend::renderer::element::surface::WaylandSurfaceRenderElement;
|
use smithay::backend::renderer::element::surface::WaylandSurfaceRenderElement;
|
||||||
use smithay::backend::renderer::element::{AsRenderElements, Id};
|
use smithay::backend::renderer::element::Id;
|
||||||
use smithay::desktop::space::SpaceElement;
|
|
||||||
use smithay::desktop::Window;
|
|
||||||
use smithay::output::Output;
|
use smithay::output::Output;
|
||||||
use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1;
|
|
||||||
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
|
|
||||||
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
||||||
use smithay::utils::{Logical, Point, Rectangle, Scale, Size, Transform};
|
use smithay::utils::{Logical, Point, Scale, Size, Transform};
|
||||||
use smithay::wayland::compositor::{send_surface_state, with_states};
|
|
||||||
use smithay::wayland::shell::xdg::SurfaceCachedState;
|
|
||||||
|
|
||||||
use self::monitor::Monitor;
|
use self::monitor::Monitor;
|
||||||
pub use self::monitor::MonitorRenderElement;
|
pub use self::monitor::MonitorRenderElement;
|
||||||
use self::workspace::{compute_working_area, Column, ColumnWidth, OutputId, Workspace};
|
use self::workspace::{compute_working_area, Column, ColumnWidth, OutputId, Workspace};
|
||||||
use crate::niri::WindowOffscreenId;
|
|
||||||
use crate::niri_render_elements;
|
use crate::niri_render_elements;
|
||||||
use crate::render_helpers::renderer::NiriRenderer;
|
use crate::render_helpers::renderer::NiriRenderer;
|
||||||
use crate::utils::output_size;
|
use crate::utils::output_size;
|
||||||
@@ -229,148 +222,6 @@ impl Options {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutElement for Window {
|
|
||||||
type Id = Self;
|
|
||||||
|
|
||||||
fn id(&self) -> &Self::Id {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size(&self) -> Size<i32, Logical> {
|
|
||||||
self.geometry().size
|
|
||||||
}
|
|
||||||
|
|
||||||
fn buf_loc(&self) -> Point<i32, Logical> {
|
|
||||||
Point::from((0, 0)) - self.geometry().loc
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_in_input_region(&self, point: Point<f64, Logical>) -> bool {
|
|
||||||
let surface_local = point + self.geometry().loc.to_f64();
|
|
||||||
SpaceElement::is_in_input_region(self, &surface_local)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render<R: NiriRenderer>(
|
|
||||||
&self,
|
|
||||||
renderer: &mut R,
|
|
||||||
location: Point<i32, Logical>,
|
|
||||||
scale: Scale<f64>,
|
|
||||||
) -> Vec<LayoutElementRenderElement<R>> {
|
|
||||||
let buf_pos = location - self.geometry().loc;
|
|
||||||
self.render_elements(
|
|
||||||
renderer,
|
|
||||||
buf_pos.to_physical_precise_round(scale),
|
|
||||||
scale,
|
|
||||||
1.,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn request_size(&self, size: Size<i32, Logical>) {
|
|
||||||
self.toplevel()
|
|
||||||
.expect("no x11 support")
|
|
||||||
.with_pending_state(|state| {
|
|
||||||
state.size = Some(size);
|
|
||||||
state.states.unset(xdg_toplevel::State::Fullscreen);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn request_fullscreen(&self, size: Size<i32, Logical>) {
|
|
||||||
self.toplevel()
|
|
||||||
.expect("no x11 support")
|
|
||||||
.with_pending_state(|state| {
|
|
||||||
state.size = Some(size);
|
|
||||||
state.states.set(xdg_toplevel::State::Fullscreen);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn min_size(&self) -> Size<i32, Logical> {
|
|
||||||
with_states(
|
|
||||||
self.toplevel().expect("no x11 support").wl_surface(),
|
|
||||||
|state| {
|
|
||||||
let curr = state.cached_state.current::<SurfaceCachedState>();
|
|
||||||
curr.min_size
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn max_size(&self) -> Size<i32, Logical> {
|
|
||||||
with_states(
|
|
||||||
self.toplevel().expect("no x11 support").wl_surface(),
|
|
||||||
|state| {
|
|
||||||
let curr = state.cached_state.current::<SurfaceCachedState>();
|
|
||||||
curr.max_size
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_wl_surface(&self, wl_surface: &WlSurface) -> bool {
|
|
||||||
self.toplevel().expect("no x11 support").wl_surface() == wl_surface
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_preferred_scale_transform(&self, scale: i32, transform: Transform) {
|
|
||||||
self.with_surfaces(|surface, data| {
|
|
||||||
send_surface_state(surface, data, scale, transform);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_ssd(&self) -> bool {
|
|
||||||
self.toplevel()
|
|
||||||
.expect("no x11 support")
|
|
||||||
.current_state()
|
|
||||||
.decoration_mode
|
|
||||||
== Some(zxdg_toplevel_decoration_v1::Mode::ServerSide)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_enter(&self, output: &Output) {
|
|
||||||
let overlap = Rectangle::from_loc_and_size((0, 0), (i32::MAX, i32::MAX));
|
|
||||||
SpaceElement::output_enter(self, output, overlap)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_leave(&self, output: &Output) {
|
|
||||||
SpaceElement::output_leave(self, output)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_offscreen_element_id(&self, id: Option<Id>) {
|
|
||||||
let data = self.user_data().get_or_insert(WindowOffscreenId::default);
|
|
||||||
data.0.replace(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_activated(&self, active: bool) {
|
|
||||||
Window::set_activated(self, active);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_bounds(&self, bounds: Size<i32, Logical>) {
|
|
||||||
self.toplevel()
|
|
||||||
.expect("no x11 support")
|
|
||||||
.with_pending_state(|state| {
|
|
||||||
state.bounds = Some(bounds);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_pending_configure(&self) {
|
|
||||||
self.toplevel()
|
|
||||||
.expect("no x11 support")
|
|
||||||
.send_pending_configure();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_fullscreen(&self) -> bool {
|
|
||||||
self.toplevel()
|
|
||||||
.expect("no x11 support")
|
|
||||||
.current_state()
|
|
||||||
.states
|
|
||||||
.contains(xdg_toplevel::State::Fullscreen)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_pending_fullscreen(&self) -> bool {
|
|
||||||
self.toplevel()
|
|
||||||
.expect("no x11 support")
|
|
||||||
.with_pending_state(|state| state.states.contains(xdg_toplevel::State::Fullscreen))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn refresh(&self) {
|
|
||||||
SpaceElement::refresh(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: LayoutElement> Layout<W> {
|
impl<W: LayoutElement> Layout<W> {
|
||||||
pub fn new(config: &Config) -> Self {
|
pub fn new(config: &Config) -> Self {
|
||||||
Self::with_options(Options::from_config(config))
|
Self::with_options(Options::from_config(config))
|
||||||
@@ -792,6 +643,29 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_window_mut(&mut self, wl_surface: &WlSurface) -> Option<&mut W> {
|
||||||
|
match &mut self.monitor_set {
|
||||||
|
MonitorSet::Normal { monitors, .. } => {
|
||||||
|
for mon in monitors {
|
||||||
|
for ws in &mut mon.workspaces {
|
||||||
|
if let Some(window) = ws.find_wl_surface_mut(wl_surface) {
|
||||||
|
return Some(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MonitorSet::NoOutputs { workspaces } => {
|
||||||
|
for ws in workspaces {
|
||||||
|
if let Some(window) = ws.find_wl_surface_mut(wl_surface) {
|
||||||
|
return Some(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn find_window_and_output(&self, wl_surface: &WlSurface) -> Option<(&W, &Output)> {
|
pub fn find_window_and_output(&self, wl_surface: &WlSurface) -> Option<(&W, &Output)> {
|
||||||
if let MonitorSet::Normal { monitors, .. } = &self.monitor_set {
|
if let MonitorSet::Normal { monitors, .. } = &self.monitor_set {
|
||||||
for mon in monitors {
|
for mon in monitors {
|
||||||
@@ -1866,6 +1740,7 @@ mod tests {
|
|||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
use proptest_derive::Arbitrary;
|
use proptest_derive::Arbitrary;
|
||||||
use smithay::output::{Mode, PhysicalProperties, Subpixel};
|
use smithay::output::{Mode, PhysicalProperties, Subpixel};
|
||||||
|
use smithay::utils::Rectangle;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|||||||
@@ -121,6 +121,10 @@ impl<W: LayoutElement> Tile<W> {
|
|||||||
&self.window
|
&self.window
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn window_mut(&mut self) -> &mut W {
|
||||||
|
&mut self.window
|
||||||
|
}
|
||||||
|
|
||||||
pub fn into_window(self) -> W {
|
pub fn into_window(self) -> W {
|
||||||
self.window
|
self.window
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-1
@@ -10,6 +10,7 @@ use smithay::output::Output;
|
|||||||
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
|
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
|
||||||
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
||||||
use smithay::utils::{Logical, Point, Rectangle, Scale, Size};
|
use smithay::utils::{Logical, Point, Rectangle, Scale, Size};
|
||||||
|
use smithay::wayland::compositor::send_surface_state;
|
||||||
|
|
||||||
use super::tile::{Tile, TileRenderElement};
|
use super::tile::{Tile, TileRenderElement};
|
||||||
use super::{LayoutElement, Options};
|
use super::{LayoutElement, Options};
|
||||||
@@ -299,6 +300,13 @@ impl<W: LayoutElement> Workspace<W> {
|
|||||||
.map(Tile::window)
|
.map(Tile::window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn windows_mut(&mut self) -> impl Iterator<Item = &mut W> + '_ {
|
||||||
|
self.columns
|
||||||
|
.iter_mut()
|
||||||
|
.flat_map(|col| col.tiles.iter_mut())
|
||||||
|
.map(Tile::window_mut)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_output(&mut self, output: Option<Output>) {
|
pub fn set_output(&mut self, output: Option<Output>) {
|
||||||
if self.output == output {
|
if self.output == output {
|
||||||
return;
|
return;
|
||||||
@@ -407,7 +415,11 @@ impl<W: LayoutElement> Workspace<W> {
|
|||||||
|
|
||||||
pub fn configure_new_window(&self, window: &Window, width: Option<ColumnWidth>) {
|
pub fn configure_new_window(&self, window: &Window, width: Option<ColumnWidth>) {
|
||||||
if let Some(output) = self.output.as_ref() {
|
if let Some(output) = self.output.as_ref() {
|
||||||
set_preferred_scale_transform(window, 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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window
|
window
|
||||||
@@ -584,6 +596,10 @@ impl<W: LayoutElement> Workspace<W> {
|
|||||||
self.windows().find(|win| win.is_wl_surface(wl_surface))
|
self.windows().find(|win| win.is_wl_surface(wl_surface))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_wl_surface_mut(&mut self, wl_surface: &WlSurface) -> Option<&mut W> {
|
||||||
|
self.windows_mut().find(|win| win.is_wl_surface(wl_surface))
|
||||||
|
}
|
||||||
|
|
||||||
/// Computes the X position of the windows in the given column, in logical coordinates.
|
/// Computes the X position of the windows in the given column, in logical coordinates.
|
||||||
fn column_x(&self, column_idx: usize) -> i32 {
|
fn column_x(&self, column_idx: usize) -> i32 {
|
||||||
let mut x = 0;
|
let mut x = 0;
|
||||||
|
|||||||
+17
-15
@@ -114,7 +114,7 @@ use crate::utils::spawning::CHILD_ENV;
|
|||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
center, center_f64, get_monotonic_time, make_screenshot_path, output_size, write_png_rgba8,
|
center, center_f64, get_monotonic_time, make_screenshot_path, output_size, write_png_rgba8,
|
||||||
};
|
};
|
||||||
use crate::window::Unmapped;
|
use crate::window::{Mapped, Unmapped};
|
||||||
use crate::{animation, niri_render_elements};
|
use crate::{animation, niri_render_elements};
|
||||||
|
|
||||||
const CLEAR_COLOR: [f32; 4] = [0.2, 0.2, 0.2, 1.];
|
const CLEAR_COLOR: [f32; 4] = [0.2, 0.2, 0.2, 1.];
|
||||||
@@ -138,7 +138,7 @@ pub struct Niri {
|
|||||||
|
|
||||||
// Each workspace corresponds to a Space. Each workspace generally has one Output mapped to it,
|
// 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).
|
// however it may have none (when there are no outputs connected) or mutiple (when mirroring).
|
||||||
pub layout: Layout<Window>,
|
pub layout: Layout<Mapped>,
|
||||||
|
|
||||||
// This space does not actually contain any windows, but all outputs are mapped into it
|
// This space does not actually contain any windows, but all outputs are mapped into it
|
||||||
// according to their global position.
|
// according to their global position.
|
||||||
@@ -631,7 +631,7 @@ impl State {
|
|||||||
self.niri
|
self.niri
|
||||||
.layout
|
.layout
|
||||||
.focus()
|
.focus()
|
||||||
.map(|win| win.toplevel().expect("no x11 support").wl_surface().clone())
|
.map(|win| win.toplevel().wl_surface().clone())
|
||||||
.map(|surface| KeyboardFocus::Layout {
|
.map(|surface| KeyboardFocus::Layout {
|
||||||
surface: Some(surface),
|
surface: Some(surface),
|
||||||
})
|
})
|
||||||
@@ -1591,7 +1591,7 @@ impl Niri {
|
|||||||
///
|
///
|
||||||
/// The cursor may be inside the window's activation region, but not within the window's input
|
/// The cursor may be inside the window's activation region, but not within the window's input
|
||||||
/// region.
|
/// region.
|
||||||
pub fn window_under(&self, pos: Point<f64, Logical>) -> Option<&Window> {
|
pub fn window_under(&self, pos: Point<f64, Logical>) -> Option<&Mapped> {
|
||||||
if self.is_locked() || self.screenshot_ui.is_open() {
|
if self.is_locked() || self.screenshot_ui.is_open() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -1618,7 +1618,7 @@ impl Niri {
|
|||||||
///
|
///
|
||||||
/// The cursor may be inside the window's activation region, but not within the window's input
|
/// The cursor may be inside the window's activation region, but not within the window's input
|
||||||
/// region.
|
/// region.
|
||||||
pub fn window_under_cursor(&self) -> Option<&Window> {
|
pub fn window_under_cursor(&self) -> Option<&Mapped> {
|
||||||
let pos = self.seat.get_pointer().unwrap().current_location();
|
let pos = self.seat.get_pointer().unwrap().current_location();
|
||||||
self.window_under(pos)
|
self.window_under(pos)
|
||||||
}
|
}
|
||||||
@@ -1684,8 +1684,9 @@ impl Niri {
|
|||||||
let window_under = || {
|
let window_under = || {
|
||||||
self.layout
|
self.layout
|
||||||
.window_under(output, pos_within_output)
|
.window_under(output, pos_within_output)
|
||||||
.and_then(|(window, win_pos_within_output)| {
|
.and_then(|(mapped, win_pos_within_output)| {
|
||||||
let win_pos_within_output = win_pos_within_output?;
|
let win_pos_within_output = win_pos_within_output?;
|
||||||
|
let window = &mapped.window;
|
||||||
window
|
window
|
||||||
.surface_under(
|
.surface_under(
|
||||||
pos_within_output - win_pos_within_output.to_f64(),
|
pos_within_output - win_pos_within_output.to_f64(),
|
||||||
@@ -2409,7 +2410,8 @@ impl Niri {
|
|||||||
// The reason to do this at all is that it keeps track of whether the surface is visible or
|
// The reason to do this at all is that it keeps track of whether the surface is visible or
|
||||||
// not in a unified way with the pointer surfaces, which makes the logic elsewhere simpler.
|
// not in a unified way with the pointer surfaces, which makes the logic elsewhere simpler.
|
||||||
|
|
||||||
for win in self.layout.windows_for_output(output) {
|
for mapped in self.layout.windows_for_output(output) {
|
||||||
|
let win = &mapped.window;
|
||||||
let offscreen_id = win
|
let offscreen_id = win
|
||||||
.user_data()
|
.user_data()
|
||||||
.get_or_insert(WindowOffscreenId::default)
|
.get_or_insert(WindowOffscreenId::default)
|
||||||
@@ -2480,8 +2482,8 @@ impl Niri {
|
|||||||
// We can unconditionally send the current output's feedback to regular and layer-shell
|
// We can unconditionally send the current output's feedback to regular and layer-shell
|
||||||
// surfaces, as they can only be displayed on a single output at a time. Even if a surface
|
// surfaces, as they can only be displayed on a single output at a time. Even if a surface
|
||||||
// is currently invisible, this is the DMABUF feedback that it should know about.
|
// is currently invisible, this is the DMABUF feedback that it should know about.
|
||||||
for win in self.layout.windows_for_output(output) {
|
for mapped in self.layout.windows_for_output(output) {
|
||||||
win.send_dmabuf_feedback(
|
mapped.window.send_dmabuf_feedback(
|
||||||
output,
|
output,
|
||||||
|_, _| Some(output.clone()),
|
|_, _| Some(output.clone()),
|
||||||
|surface, _| {
|
|surface, _| {
|
||||||
@@ -2600,8 +2602,8 @@ impl Niri {
|
|||||||
|
|
||||||
let frame_callback_time = get_monotonic_time();
|
let frame_callback_time = get_monotonic_time();
|
||||||
|
|
||||||
for win in self.layout.windows_for_output(output) {
|
for mapped in self.layout.windows_for_output(output) {
|
||||||
win.send_frame(
|
mapped.window.send_frame(
|
||||||
output,
|
output,
|
||||||
frame_callback_time,
|
frame_callback_time,
|
||||||
FRAME_CALLBACK_THROTTLE,
|
FRAME_CALLBACK_THROTTLE,
|
||||||
@@ -2666,8 +2668,8 @@ impl Niri {
|
|||||||
|
|
||||||
let frame_callback_time = get_monotonic_time();
|
let frame_callback_time = get_monotonic_time();
|
||||||
|
|
||||||
self.layout.with_windows(|win, _| {
|
self.layout.with_windows(|mapped, _| {
|
||||||
win.send_frame(
|
mapped.window.send_frame(
|
||||||
output,
|
output,
|
||||||
frame_callback_time,
|
frame_callback_time,
|
||||||
FRAME_CALLBACK_THROTTLE,
|
FRAME_CALLBACK_THROTTLE,
|
||||||
@@ -2746,8 +2748,8 @@ impl Niri {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for win in self.layout.windows_for_output(output) {
|
for mapped in self.layout.windows_for_output(output) {
|
||||||
win.take_presentation_feedback(
|
mapped.window.take_presentation_feedback(
|
||||||
&mut feedback,
|
&mut feedback,
|
||||||
surface_primary_scanout_output,
|
surface_primary_scanout_output,
|
||||||
|surface, _| {
|
|surface, _| {
|
||||||
|
|||||||
@@ -95,8 +95,8 @@ pub fn refresh(state: &mut State) {
|
|||||||
// Save the focused window for last, this way when the focus changes, we will first deactivate
|
// Save the focused window for last, this way when the focus changes, we will first deactivate
|
||||||
// the previous window and only then activate the newly focused window.
|
// the previous window and only then activate the newly focused window.
|
||||||
let mut focused = None;
|
let mut focused = None;
|
||||||
state.niri.layout.with_windows(|window, output| {
|
state.niri.layout.with_windows(|mapped, output| {
|
||||||
let wl_surface = window.toplevel().expect("no x11 support").wl_surface();
|
let wl_surface = mapped.toplevel().wl_surface();
|
||||||
|
|
||||||
with_states(wl_surface, |states| {
|
with_states(wl_surface, |states| {
|
||||||
let role = states
|
let role = states
|
||||||
@@ -107,7 +107,7 @@ pub fn refresh(state: &mut State) {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if state.niri.keyboard_focus.surface() == Some(wl_surface) {
|
if state.niri.keyboard_focus.surface() == Some(wl_surface) {
|
||||||
focused = Some((window.clone(), output.cloned()));
|
focused = Some((mapped.window.clone(), output.cloned()));
|
||||||
} else {
|
} else {
|
||||||
refresh_toplevel(protocol_state, wl_surface, &role, output, false);
|
refresh_toplevel(protocol_state, wl_surface, &role, output, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ pub mod watcher;
|
|||||||
|
|
||||||
pub static IS_SYSTEMD_SERVICE: AtomicBool = AtomicBool::new(false);
|
pub static IS_SYSTEMD_SERVICE: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
pub fn clone2<T: Clone, U: Clone>(t: (&T, &U)) -> (T, U) {
|
|
||||||
(t.0.clone(), t.1.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn version() -> String {
|
pub fn version() -> String {
|
||||||
format!(
|
format!(
|
||||||
"{} ({})",
|
"{} ({})",
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
use smithay::backend::renderer::element::{AsRenderElements as _, Id};
|
||||||
|
use smithay::desktop::space::SpaceElement as _;
|
||||||
|
use smithay::desktop::Window;
|
||||||
|
use smithay::output::Output;
|
||||||
|
use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1;
|
||||||
|
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
|
||||||
|
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
||||||
|
use smithay::utils::{Logical, Point, Rectangle, Scale, Size, Transform};
|
||||||
|
use smithay::wayland::compositor::{send_surface_state, with_states};
|
||||||
|
use smithay::wayland::shell::xdg::{SurfaceCachedState, ToplevelSurface};
|
||||||
|
|
||||||
|
use super::ResolvedWindowRules;
|
||||||
|
use crate::layout::{LayoutElement, LayoutElementRenderElement};
|
||||||
|
use crate::niri::WindowOffscreenId;
|
||||||
|
use crate::render_helpers::renderer::NiriRenderer;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Mapped {
|
||||||
|
pub window: Window,
|
||||||
|
|
||||||
|
/// Up-to-date rules.
|
||||||
|
pub rules: ResolvedWindowRules,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mapped {
|
||||||
|
pub fn new(window: Window, rules: ResolvedWindowRules) -> Self {
|
||||||
|
Self { window, rules }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toplevel(&self) -> &ToplevelSurface {
|
||||||
|
self.window.toplevel().expect("no X11 support")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutElement for Mapped {
|
||||||
|
type Id = Window;
|
||||||
|
|
||||||
|
fn id(&self) -> &Self::Id {
|
||||||
|
&self.window
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> Size<i32, Logical> {
|
||||||
|
self.window.geometry().size
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buf_loc(&self) -> Point<i32, Logical> {
|
||||||
|
Point::from((0, 0)) - self.window.geometry().loc
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_in_input_region(&self, point: Point<f64, Logical>) -> bool {
|
||||||
|
let surface_local = point + self.window.geometry().loc.to_f64();
|
||||||
|
self.window.is_in_input_region(&surface_local)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<R: NiriRenderer>(
|
||||||
|
&self,
|
||||||
|
renderer: &mut R,
|
||||||
|
location: Point<i32, Logical>,
|
||||||
|
scale: Scale<f64>,
|
||||||
|
) -> Vec<LayoutElementRenderElement<R>> {
|
||||||
|
let buf_pos = location - self.window.geometry().loc;
|
||||||
|
self.window.render_elements(
|
||||||
|
renderer,
|
||||||
|
buf_pos.to_physical_precise_round(scale),
|
||||||
|
scale,
|
||||||
|
1.,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn request_size(&self, size: Size<i32, Logical>) {
|
||||||
|
self.toplevel().with_pending_state(|state| {
|
||||||
|
state.size = Some(size);
|
||||||
|
state.states.unset(xdg_toplevel::State::Fullscreen);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn request_fullscreen(&self, size: Size<i32, Logical>) {
|
||||||
|
self.toplevel().with_pending_state(|state| {
|
||||||
|
state.size = Some(size);
|
||||||
|
state.states.set(xdg_toplevel::State::Fullscreen);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn min_size(&self) -> Size<i32, Logical> {
|
||||||
|
with_states(self.toplevel().wl_surface(), |state| {
|
||||||
|
let curr = state.cached_state.current::<SurfaceCachedState>();
|
||||||
|
curr.min_size
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_size(&self) -> Size<i32, Logical> {
|
||||||
|
with_states(self.toplevel().wl_surface(), |state| {
|
||||||
|
let curr = state.cached_state.current::<SurfaceCachedState>();
|
||||||
|
curr.max_size
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_wl_surface(&self, wl_surface: &WlSurface) -> bool {
|
||||||
|
self.toplevel().wl_surface() == wl_surface
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_preferred_scale_transform(&self, scale: i32, transform: Transform) {
|
||||||
|
self.window.with_surfaces(|surface, data| {
|
||||||
|
send_surface_state(surface, data, scale, transform);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_ssd(&self) -> bool {
|
||||||
|
self.toplevel().current_state().decoration_mode
|
||||||
|
== Some(zxdg_toplevel_decoration_v1::Mode::ServerSide)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_enter(&self, output: &Output) {
|
||||||
|
let overlap = Rectangle::from_loc_and_size((0, 0), (i32::MAX, i32::MAX));
|
||||||
|
self.window.output_enter(output, overlap)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_leave(&self, output: &Output) {
|
||||||
|
self.window.output_leave(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_offscreen_element_id(&self, id: Option<Id>) {
|
||||||
|
let data = self
|
||||||
|
.window
|
||||||
|
.user_data()
|
||||||
|
.get_or_insert(WindowOffscreenId::default);
|
||||||
|
data.0.replace(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_activated(&self, active: bool) {
|
||||||
|
self.window.set_activated(active);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_bounds(&self, bounds: Size<i32, Logical>) {
|
||||||
|
self.toplevel().with_pending_state(|state| {
|
||||||
|
state.bounds = Some(bounds);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_pending_configure(&self) {
|
||||||
|
self.toplevel().send_pending_configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_fullscreen(&self) -> bool {
|
||||||
|
self.toplevel()
|
||||||
|
.current_state()
|
||||||
|
.states
|
||||||
|
.contains(xdg_toplevel::State::Fullscreen)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_pending_fullscreen(&self) -> bool {
|
||||||
|
self.toplevel()
|
||||||
|
.with_pending_state(|state| state.states.contains(xdg_toplevel::State::Fullscreen))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn refresh(&self) {
|
||||||
|
self.window.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
use crate::layout::workspace::ColumnWidth;
|
use crate::layout::workspace::ColumnWidth;
|
||||||
|
|
||||||
|
pub mod mapped;
|
||||||
|
pub use mapped::Mapped;
|
||||||
|
|
||||||
pub mod unmapped;
|
pub mod unmapped;
|
||||||
pub use unmapped::{InitialConfigureState, Unmapped};
|
pub use unmapped::{InitialConfigureState, Unmapped};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user