Skip to content

Commit

Permalink
Implement wlr-foreign-toplevel-management
Browse files Browse the repository at this point in the history
The parent event isn't sent but whatever.
  • Loading branch information
YaLTeR committed Jan 29, 2024
1 parent 597ea62 commit a6aaacf
Show file tree
Hide file tree
Showing 6 changed files with 505 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use smithay::input::pointer::{CursorIcon, CursorImageStatus, PointerHandle};
use smithay::input::{keyboard, Seat, SeatHandler, SeatState};
use smithay::output::Output;
use smithay::reexports::input;
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
use smithay::reexports::wayland_server::protocol::wl_data_source::WlDataSource;
use smithay::reexports::wayland_server::protocol::wl_output::WlOutput;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
Expand Down Expand Up @@ -46,7 +47,9 @@ use smithay::{
delegate_tablet_manager, delegate_text_input_manager, delegate_virtual_keyboard_manager,
};

use crate::delegate_foreign_toplevel;
use crate::niri::{ClientState, State};
use crate::protocols::foreign_toplevel::{ForeignToplevelHandler, ForeignToplevelManagerState};
use crate::utils::output_size;

impl SeatHandler for State {
Expand Down Expand Up @@ -291,3 +294,57 @@ impl SecurityContextHandler for State {
}
}
delegate_security_context!(State);

impl ForeignToplevelHandler for State {
fn foreign_toplevel_manager_state(&mut self) -> &mut ForeignToplevelManagerState {
&mut self.niri.foreign_toplevel_state
}

fn activate(&mut self, wl_surface: WlSurface) {
if let Some((window, _)) = self.niri.layout.find_window_and_output(&wl_surface) {
let window = window.clone();
self.niri.layout.activate_window(&window);
self.niri.queue_redraw_all();
}
}

fn close(&mut self, wl_surface: WlSurface) {
if let Some((window, _)) = self.niri.layout.find_window_and_output(&wl_surface) {
window.toplevel().send_close();
}
}

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 !window
.toplevel()
.current_state()
.capabilities
.contains(xdg_toplevel::WmCapabilities::Fullscreen)
{
return;
}

let window = window.clone();

if let Some(requested_output) = wl_output.as_ref().and_then(Output::from_resource) {
if &requested_output != current_output {
self.niri
.layout
.move_window_to_output(window.clone(), &requested_output);
}
}

self.niri.layout.set_fullscreen(&window, true);
}
}

fn unset_fullscreen(&mut self, wl_surface: WlSurface) {
if let Some((window, _)) = self.niri.layout.find_window_and_output(&wl_surface) {
let window = window.clone();
self.niri.layout.set_fullscreen(&window, false);
}
}
}
delegate_foreign_toplevel!(State);
21 changes: 21 additions & 0 deletions src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,27 @@ impl<W: LayoutElement> Layout<W> {
mon.workspaces.iter().flat_map(|ws| ws.windows())
}

pub fn with_windows(&self, mut f: impl FnMut(&W, Option<&Output>)) {
match &self.monitor_set {
MonitorSet::Normal { monitors, .. } => {
for mon in monitors {
for ws in &mon.workspaces {
for win in ws.windows() {
f(win, Some(&mon.output));
}
}
}
}
MonitorSet::NoOutputs { workspaces } => {
for ws in workspaces {
for win in ws.windows() {
f(win, None);
}
}
}
}
}

fn active_monitor(&mut self) -> Option<&mut Monitor<W>> {
let MonitorSet::Normal {
monitors,
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod input;
mod ipc;
mod layout;
mod niri;
mod protocols;
mod render_helpers;
mod screenshot_ui;
mod utils;
Expand Down
9 changes: 9 additions & 0 deletions src/niri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ use crate::hotkey_overlay::HotkeyOverlay;
use crate::input::{apply_libinput_settings, TabletData};
use crate::ipc::server::IpcServer;
use crate::layout::{Layout, MonitorRenderElement};
use crate::protocols::foreign_toplevel::{self, ForeignToplevelManagerState};
use crate::pw_utils::{Cast, PipeWire};
use crate::render_helpers::NiriRenderer;
use crate::screenshot_ui::{ScreenshotUi, ScreenshotUiRenderElement};
Expand Down Expand Up @@ -151,6 +152,7 @@ pub struct Niri {
pub kde_decoration_state: KdeDecorationState,
pub layer_shell_state: WlrLayerShellState,
pub session_lock_state: SessionLockManagerState,
pub foreign_toplevel_state: ForeignToplevelManagerState,
pub shm_state: ShmState,
pub output_manager_state: OutputManagerState,
pub dmabuf_state: DmabufState,
Expand Down Expand Up @@ -327,6 +329,7 @@ impl State {
self.refresh_popup_grab();
self.update_keyboard_focus();
self.refresh_pointer_focus();
foreign_toplevel::refresh(self);

{
let _span = tracy_client::span!("flush_clients");
Expand Down Expand Up @@ -855,6 +858,11 @@ impl Niri {
!client.get_data::<ClientState>().unwrap().restricted
});

let foreign_toplevel_state =
ForeignToplevelManagerState::new::<State, _>(&display_handle, |client| {
!client.get_data::<ClientState>().unwrap().restricted
});

let mut seat: Seat<State> = seat_state.new_wl_seat(&display_handle, backend.seat_name());
seat.add_keyboard(
config_.input.keyboard.xkb.to_xkb_config(),
Expand Down Expand Up @@ -972,6 +980,7 @@ impl Niri {
kde_decoration_state,
layer_shell_state,
session_lock_state,
foreign_toplevel_state,
text_input_state,
input_method_state,
virtual_keyboard_state,
Expand Down
Loading

0 comments on commit a6aaacf

Please sign in to comment.