use smithay::desktop::{
find_popup_root_surface, get_popup_toplevel_coords, layer_map_for_output, utils, LayerSurface,
PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab, PopupUngrabStrategy, Window,
WindowSurfaceType,
};
use smithay::input::pointer::Focus;
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_positioner::ConstraintAdjustment;
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::{self};
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::reexports::wayland_server::Resource;
use smithay::utils::{Logical, Rectangle, Serial};
use smithay::wayland::compositor::{
add_pre_commit_hook, send_surface_state, with_states, BufferAssignment, HookId,
SurfaceAttributes,
};
use smithay::wayland::input_method::InputMethodSeat;
use smithay::wayland::shell::kde::decoration::{KdeDecorationHandler, KdeDecorationState};
use smithay::wayland::shell::wlr_layer::{self, Layer};
use smithay::wayland::shell::xdg::decoration::XdgDecorationHandler;
use smithay::wayland::shell::xdg::{
PopupSurface, PositionerState, ToplevelSurface, XdgPopupSurfaceData, XdgShellHandler,
XdgShellState, XdgToplevelSurfaceData,
};
use smithay::wayland::xdg_foreign::{XdgForeignHandler, XdgForeignState};
use smithay::{
delegate_kde_decoration, delegate_xdg_decoration, delegate_xdg_foreign, delegate_xdg_shell,
};
use crate::input::resize_grab::ResizeGrab;
use crate::input::DOUBLE_CLICK_TIME;
use crate::layout::workspace::ColumnWidth;
use crate::niri::{PopupGrabState, State};
use crate::utils::{get_monotonic_time, ResizeEdge};
use crate::window::{InitialConfigureState, ResolvedWindowRules, Unmapped, WindowRef};
impl XdgShellHandler for State {
fn xdg_shell_state(&mut self) -> &mut XdgShellState {
&mut self.niri.xdg_shell_state
}
fn new_toplevel(&mut self, surface: ToplevelSurface) {
let wl_surface = surface.wl_surface().clone();
let unmapped = Unmapped::new(Window::new_wayland_window(surface));
let existing = self.niri.unmapped_windows.insert(wl_surface, unmapped);
assert!(existing.is_none());
}
fn new_popup(&mut self, surface: PopupSurface, _positioner: PositionerState) {
let popup = PopupKind::Xdg(surface);
self.unconstrain_popup(&popup);
if let Err(err) = self.niri.popups.track_popup(popup) {
warn!("error tracking popup: {err:?}");
}
}
fn move_request(&mut self, _surface: ToplevelSurface, _seat: WlSeat, _serial: Serial) {
// FIXME
}
fn resize_request(
&mut self,
surface: ToplevelSurface,
_seat: WlSeat,
serial: Serial,
edges: xdg_toplevel::ResizeEdge,
) {
let pointer = self.niri.seat.get_pointer().unwrap();
if !pointer.has_grab(serial) {
return;
}
let Some(start_data) = pointer.grab_start_data() else {
return;
};
let Some((focus, _)) = &start_data.focus else {
return;
};
let wl_surface = surface.wl_surface();
if !focus.id().same_client_as(&wl_surface.id()) {
return;
}
let Some((mapped, _)) = self.niri.layout.find_window_and_output(wl_surface) else {
return;
};
let edges = ResizeEdge::from(edges);
let window = mapped.window.clone();
// See if we got a double resize-click gesture.
let time = get_monotonic_time();
let last_cell = mapped.last_interactive_resize_start();
let last = last_cell.get();
last_cell.set(Some((time, edges)));
if let Some((last_time, last