Add maximized requests and fullscreen requests for xwayland

This commit is contained in:
Ottatop 2023-08-12 18:13:30 -05:00
parent e2dea4dd15
commit 947ccdf464
3 changed files with 153 additions and 109 deletions

View file

@ -322,6 +322,8 @@ impl<B: Backend> XdgShellHandler for State<B> {
tracing::error!("wl_surface had no window");
return;
};
window.set_status(StatusName::Fullscreen);
}
surface.send_configure();
@ -343,6 +345,33 @@ impl<B: Backend> XdgShellHandler for State<B> {
});
surface.send_pending_configure();
let Some(window) = self.window_for_surface(surface.wl_surface()) else {
tracing::error!("wl_surface had no window");
return;
};
// TODO: remember the last status instead of tiled
window.set_status(StatusName::Tiled);
}
fn maximize_request(&mut self, surface: ToplevelSurface) {
let Some(window) = self.window_for_surface(surface.wl_surface()) else {
return;
};
window.set_status(StatusName::Maximized);
// TODO: might need to update_windows here
}
fn unmaximize_request(&mut self, surface: ToplevelSurface) {
let Some(window) = self.window_for_surface(surface.wl_surface()) else {
return;
};
// TODO: remember last status
window.set_status(StatusName::Tiled);
}
// fn minimize_request(&mut self, surface: ToplevelSurface) {

View file

@ -28,7 +28,10 @@ use crate::{
backend::Backend,
focus::FocusTarget,
state::{CalloopData, WithState},
window::{window_state::Status, WindowBlocker, WindowElement, BLOCKER_COUNTER},
window::{
window_state::{Status, StatusName},
WindowBlocker, WindowElement, BLOCKER_COUNTER,
},
};
impl<B: Backend> XwmHandler for CalloopData<B> {
@ -331,22 +334,50 @@ impl<B: Backend> XwmHandler for CalloopData<B> {
// TODO: anvil has a TODO here
}
// fn maximize_request(&mut self, xwm: XwmId, window: X11Surface) {
// // TODO:
// }
//
// fn unmaximize_request(&mut self, xwm: XwmId, window: X11Surface) {
// // TODO:
// }
//
// fn fullscreen_request(&mut self, xwm: XwmId, window: X11Surface) {
// // TODO:
// // window.set_fullscreen(true).unwrap();
// }
//
// fn unfullscreen_request(&mut self, xwm: XwmId, window: X11Surface) {
// // TODO:
// }
fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
window
.set_maximized(true)
.expect("failed to set x11 win to maximized");
let Some(window) = (|| self.state.window_for_surface(&window.wl_surface()?))() else {
return;
};
window.set_status(StatusName::Maximized);
}
fn unmaximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
window
.set_maximized(false)
.expect("failed to set x11 win to maximized");
let Some(window) = (|| self.state.window_for_surface(&window.wl_surface()?))() else {
return;
};
// TODO: remember previous status
window.set_status(StatusName::Tiled);
}
fn fullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) {
window
.set_fullscreen(true)
.expect("failed to set x11 win to fullscreen");
// TODO: fix this mess
let Some(window) = (|| self.state.window_for_surface(&window.wl_surface()?))() else {
return;
};
window.set_status(StatusName::Fullscreen);
// TODO: do i need to update_windows here?
}
fn unfullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) {
window
.set_fullscreen(false)
.expect("failed to set x11 win to unfullscreen");
let Some(window) = (|| self.state.window_for_surface(&window.wl_surface()?))() else {
return;
};
// TODO: remember previous status
window.set_status(StatusName::Tiled);
}
fn resize_request(
&mut self,

View file

@ -283,57 +283,97 @@ impl WindowElement {
StatusName::Floating => {
self.with_state(|state| state.status = Status::Floating(geo));
if let WindowElement::Wayland(window) = self {
window.toplevel().with_pending_state(|state| {
state.states.unset(xdg_toplevel::State::Maximized);
state.states.unset(xdg_toplevel::State::Fullscreen);
state.states.unset(xdg_toplevel::State::TiledTop);
state.states.unset(xdg_toplevel::State::TiledBottom);
state.states.unset(xdg_toplevel::State::TiledLeft);
state.states.unset(xdg_toplevel::State::TiledRight);
});
match self {
WindowElement::Wayland(window) => {
window.toplevel().with_pending_state(|state| {
state.states.unset(xdg_toplevel::State::Maximized);
state.states.unset(xdg_toplevel::State::Fullscreen);
state.states.unset(xdg_toplevel::State::TiledTop);
state.states.unset(xdg_toplevel::State::TiledBottom);
state.states.unset(xdg_toplevel::State::TiledLeft);
state.states.unset(xdg_toplevel::State::TiledRight);
});
}
WindowElement::X11(surface) => {
surface
.set_fullscreen(false)
.expect("failed to set x11 win to not fullscreen");
surface
.set_maximized(false)
.expect("failed to set x11 win to not maximized");
}
}
}
StatusName::Tiled => {
self.with_state(|state| state.status = Status::Tiled(Some(geo)));
if let WindowElement::Wayland(window) = self {
window.toplevel().with_pending_state(|state| {
state.states.unset(xdg_toplevel::State::Maximized);
state.states.unset(xdg_toplevel::State::Fullscreen);
state.states.set(xdg_toplevel::State::TiledTop);
state.states.set(xdg_toplevel::State::TiledBottom);
state.states.set(xdg_toplevel::State::TiledLeft);
state.states.set(xdg_toplevel::State::TiledRight);
});
match self {
WindowElement::Wayland(window) => {
window.toplevel().with_pending_state(|state| {
state.states.unset(xdg_toplevel::State::Maximized);
state.states.unset(xdg_toplevel::State::Fullscreen);
state.states.set(xdg_toplevel::State::TiledTop);
state.states.set(xdg_toplevel::State::TiledBottom);
state.states.set(xdg_toplevel::State::TiledLeft);
state.states.set(xdg_toplevel::State::TiledRight);
});
}
WindowElement::X11(surface) => {
surface
.set_fullscreen(false)
.expect("failed to set x11 win to not fullscreen");
surface
.set_maximized(false)
.expect("failed to set x11 win to not maximized");
}
}
}
StatusName::Fullscreen => {
self.with_state(|state| state.status = Status::Fullscreen(Some(geo)));
if let WindowElement::Wayland(window) = self {
window.toplevel().with_pending_state(|state| {
state.states.unset(xdg_toplevel::State::Maximized);
state.states.set(xdg_toplevel::State::Fullscreen);
state.states.set(xdg_toplevel::State::TiledTop);
state.states.set(xdg_toplevel::State::TiledBottom);
state.states.set(xdg_toplevel::State::TiledLeft);
state.states.set(xdg_toplevel::State::TiledRight);
});
match self {
WindowElement::Wayland(window) => {
window.toplevel().with_pending_state(|state| {
state.states.unset(xdg_toplevel::State::Maximized);
state.states.set(xdg_toplevel::State::Fullscreen);
state.states.set(xdg_toplevel::State::TiledTop);
state.states.set(xdg_toplevel::State::TiledBottom);
state.states.set(xdg_toplevel::State::TiledLeft);
state.states.set(xdg_toplevel::State::TiledRight);
});
}
WindowElement::X11(surface) => {
surface
.set_fullscreen(true)
.expect("failed to set x11 win to fullscreen");
surface
.set_maximized(false)
.expect("failed to set x11 win to not maximzied");
}
}
}
StatusName::Maximized => {
self.with_state(|state| state.status = Status::Maximized(Some(geo)));
if let WindowElement::Wayland(window) = self {
window.toplevel().with_pending_state(|state| {
state.states.unset(xdg_toplevel::State::Fullscreen);
state.states.set(xdg_toplevel::State::Maximized);
state.states.set(xdg_toplevel::State::TiledTop);
state.states.set(xdg_toplevel::State::TiledBottom);
state.states.set(xdg_toplevel::State::TiledLeft);
state.states.set(xdg_toplevel::State::TiledRight);
});
match self {
WindowElement::Wayland(window) => {
window.toplevel().with_pending_state(|state| {
state.states.unset(xdg_toplevel::State::Fullscreen);
state.states.set(xdg_toplevel::State::Maximized);
state.states.set(xdg_toplevel::State::TiledTop);
state.states.set(xdg_toplevel::State::TiledBottom);
state.states.set(xdg_toplevel::State::TiledLeft);
state.states.set(xdg_toplevel::State::TiledRight);
});
}
WindowElement::X11(surface) => {
surface
.set_fullscreen(false)
.expect("failed to set x11 win to not fullscreen");
surface
.set_maximized(true)
.expect("failed to set x11 win to maximized");
}
}
}
}
@ -571,62 +611,6 @@ impl<B: Backend> State<B> {
}
}
/// Toggle a window's floating status.
pub fn toggle_floating<B: Backend>(state: &mut State<B>, window: &WindowElement) {
match window.with_state(|state| state.status) {
Status::Floating(_) => window.set_status(StatusName::Tiled),
Status::Tiled(_) => window.set_status(StatusName::Fullscreen),
Status::Fullscreen(_) => window.set_status(StatusName::Maximized),
Status::Maximized(_) => window.set_status(StatusName::Floating),
}
// TODO: don't use the focused output, use the one the window is on
let output = state
.focus_state
.focused_output
.clone()
.expect("no focused output");
// state.re_layout(&output);
state.update_windows(&output);
let render = output.with_state(|op_state| {
state
.windows
.iter()
.cloned()
.filter(|win| {
win.with_state(|win_state| {
if win_state.status.is_floating() {
return true;
}
for tag in win_state.tags.iter() {
if op_state.focused_tags().any(|tg| tg == tag) {
return true;
}
}
false
})
})
.filter(|win| win != window)
.collect::<Vec<_>>()
});
let clone = window.clone();
state.loop_handle.insert_idle(move |data| {
crate::state::schedule_on_commit(data, render, move |dt| {
dt.state.space.raise_element(&clone, true);
if let WindowElement::X11(surface) = clone {
dt.state
.xwm
.as_mut()
.expect("no xwm")
.raise_window(&surface)
.expect("failed to raise x11 win");
}
});
});
}
pub struct WindowBlocker;
pub static BLOCKER_COUNTER: AtomicU32 = AtomicU32::new(0);