mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Remove space_elements!
so uh when you impl SpaceElement you gotta actually remember to impl the geometry fn, which is why Alacritty was 44 pixels off in the other attempt at this
This commit is contained in:
parent
16fff3f7e3
commit
48cd3d0df9
12 changed files with 379 additions and 733 deletions
88
src/api.rs
88
src/api.rs
|
@ -34,11 +34,11 @@ use pinnacle_api_defs::pinnacle::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
desktop::space::SpaceElement,
|
desktop::{space::SpaceElement, WindowSurface},
|
||||||
input::keyboard::XkbConfig,
|
input::keyboard::XkbConfig,
|
||||||
reexports::{calloop, input as libinput, wayland_protocols::xdg::shell::server},
|
reexports::{calloop, input as libinput, wayland_protocols::xdg::shell::server},
|
||||||
utils::{Point, Rectangle, SERIAL_COUNTER},
|
utils::{Point, Rectangle, SERIAL_COUNTER},
|
||||||
wayland::{compositor, shell::xdg::XdgToplevelSurfaceData},
|
wayland::seat::WaylandFocus,
|
||||||
};
|
};
|
||||||
use sysinfo::ProcessRefreshKind;
|
use sysinfo::ProcessRefreshKind;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
|
@ -48,6 +48,7 @@ use tokio::{
|
||||||
};
|
};
|
||||||
use tokio_stream::{Stream, StreamExt};
|
use tokio_stream::{Stream, StreamExt};
|
||||||
use tonic::{Request, Response, Status, Streaming};
|
use tonic::{Request, Response, Status, Streaming};
|
||||||
|
use tracing::{error, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::ConnectorSavedState,
|
config::ConnectorSavedState,
|
||||||
|
@ -56,7 +57,7 @@ use crate::{
|
||||||
output::OutputName,
|
output::OutputName,
|
||||||
state::{State, WithState},
|
state::{State, WithState},
|
||||||
tag::{Tag, TagId},
|
tag::{Tag, TagId},
|
||||||
window::{window_state::WindowId, WindowElement},
|
window::window_state::WindowId,
|
||||||
};
|
};
|
||||||
|
|
||||||
type ResponseStream<T> = Pin<Box<dyn Stream<Item = Result<T, Status>> + Send>>;
|
type ResponseStream<T> = Pin<Box<dyn Stream<Item = Result<T, Status>> + Send>>;
|
||||||
|
@ -316,7 +317,7 @@ impl input_service_server::InputService for InputService {
|
||||||
};
|
};
|
||||||
if let Some(kb) = state.seat.get_keyboard() {
|
if let Some(kb) = state.seat.get_keyboard() {
|
||||||
if let Err(err) = kb.set_xkb_config(state, new_config) {
|
if let Err(err) = kb.set_xkb_config(state, new_config) {
|
||||||
tracing::error!("Failed to set xkbconfig: {err}");
|
error!("Failed to set xkbconfig: {err}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -557,7 +558,7 @@ impl process_service_server::ProcessService for ProcessService {
|
||||||
.args(command)
|
.args(command)
|
||||||
.spawn()
|
.spawn()
|
||||||
else {
|
else {
|
||||||
tracing::warn!("Tried to run {arg0}, but it doesn't exist",);
|
warn!("Tried to run {arg0}, but it doesn't exist",);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -584,7 +585,7 @@ impl process_service_server::ProcessService for ProcessService {
|
||||||
match sender.send(response) {
|
match sender.send(response) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::error!(err = ?err);
|
error!(err = ?err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,7 +609,7 @@ impl process_service_server::ProcessService for ProcessService {
|
||||||
match sender.send(response) {
|
match sender.send(response) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::error!(err = ?err);
|
error!(err = ?err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -627,7 +628,7 @@ impl process_service_server::ProcessService for ProcessService {
|
||||||
// TODO: handle error
|
// TODO: handle error
|
||||||
let _ = sender.send(response);
|
let _ = sender.send(response);
|
||||||
}
|
}
|
||||||
Err(err) => tracing::warn!("child wait() err: {err}"),
|
Err(err) => warn!("child wait() err: {err}"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -1122,15 +1123,17 @@ impl window_service_server::WindowService for WindowService {
|
||||||
run_unary_no_response(&self.sender, move |state| {
|
run_unary_no_response(&self.sender, move |state| {
|
||||||
let Some(window) = window_id.window(state) else { return };
|
let Some(window) = window_id.window(state) else { return };
|
||||||
|
|
||||||
match window {
|
match window.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => toplevel.send_close(),
|
||||||
window.toplevel().expect("in wayland enum").send_close()
|
WindowSurface::X11(surface) => {
|
||||||
|
if !surface.is_override_redirect() {
|
||||||
|
if let Err(err) = surface.close() {
|
||||||
|
error!("failed to close x11 window: {err}");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("tried to close OR window");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) => surface.close().expect("failed to close x11 win"),
|
|
||||||
WindowElement::X11OverrideRedirect(_) => {
|
|
||||||
tracing::warn!("tried to close override redirect window");
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -1356,32 +1359,14 @@ impl window_service_server::WindowService for WindowService {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if window.is_x11_override_redirect() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let Some(output) = window.output(state) else {
|
let Some(output) = window.output(state) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
// if !matches!(
|
|
||||||
// &focus,
|
|
||||||
// FocusTarget::Window(WindowElement::X11OverrideRedirect(_))
|
|
||||||
// ) {
|
|
||||||
// keyboard.set_focus(self, Some(focus.clone()), serial);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// self.space.elements().for_each(|window| {
|
|
||||||
// if let WindowElement::Wayland(window) = window {
|
|
||||||
// window.toplevel().send_configure();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// self.space.elements().for_each(|window| {
|
|
||||||
// window.set_activate(false);
|
|
||||||
// if let WindowElement::Wayland(window) = window {
|
|
||||||
// window.toplevel().send_configure();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// keyboard.set_focus(self, None, serial);
|
|
||||||
// }
|
|
||||||
|
|
||||||
for win in state.space.elements() {
|
for win in state.space.elements() {
|
||||||
win.set_activate(false);
|
win.set_activate(false);
|
||||||
}
|
}
|
||||||
|
@ -1432,8 +1417,8 @@ impl window_service_server::WindowService for WindowService {
|
||||||
}
|
}
|
||||||
|
|
||||||
for window in state.space.elements() {
|
for window in state.space.elements() {
|
||||||
if let WindowElement::Wayland(window) = window {
|
if let Some(toplevel) = window.toplevel() {
|
||||||
window.toplevel().expect("in wayland enum").send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1677,27 +1662,8 @@ impl window_service_server::WindowService for WindowService {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let (class, title) = window.as_ref().map_or((None, None), |win| match &win {
|
let class = window.as_ref().and_then(|win| win.class());
|
||||||
WindowElement::Wayland(_) => {
|
let title = window.as_ref().and_then(|win| win.title());
|
||||||
if let Some(wl_surf) = win.wl_surface() {
|
|
||||||
compositor::with_states(&wl_surf, |states| {
|
|
||||||
let lock = states
|
|
||||||
.data_map
|
|
||||||
.get::<XdgToplevelSurfaceData>()
|
|
||||||
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
|
|
||||||
.lock()
|
|
||||||
.expect("failed to acquire lock");
|
|
||||||
(lock.app_id.clone(), lock.title.clone())
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
(None, None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
(Some(surface.class()), Some(surface.title()))
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let focused = window.as_ref().and_then(|win| {
|
let focused = window.as_ref().and_then(|win| {
|
||||||
state
|
state
|
||||||
|
|
10
src/focus.rs
10
src/focus.rs
|
@ -56,8 +56,8 @@ impl State {
|
||||||
if let Some(win) = ¤t_focus {
|
if let Some(win) = ¤t_focus {
|
||||||
assert!(!win.is_x11_override_redirect());
|
assert!(!win.is_x11_override_redirect());
|
||||||
|
|
||||||
if let WindowElement::Wayland(w) = win {
|
if let Some(toplevel) = win.toplevel() {
|
||||||
w.toplevel().expect("in wayland enum").send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,13 +437,9 @@ impl WaylandFocus for FocusTarget {
|
||||||
object_id: &smithay::reexports::wayland_server::backend::ObjectId,
|
object_id: &smithay::reexports::wayland_server::backend::ObjectId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match self {
|
match self {
|
||||||
FocusTarget::Window(WindowElement::Wayland(window)) => window.same_client_as(object_id),
|
FocusTarget::Window(window) => window.same_client_as(object_id),
|
||||||
FocusTarget::Window(
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface),
|
|
||||||
) => surface.same_client_as(object_id),
|
|
||||||
FocusTarget::Popup(popup) => popup.wl_surface().id().same_client_as(object_id),
|
FocusTarget::Popup(popup) => popup.wl_surface().id().same_client_as(object_id),
|
||||||
FocusTarget::LayerSurface(surf) => surf.wl_surface().id().same_client_as(object_id),
|
FocusTarget::LayerSurface(surf) => surf.wl_surface().id().same_client_as(object_id),
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,13 +51,16 @@ impl PointerGrab<State> for MoveSurfaceGrab {
|
||||||
}
|
}
|
||||||
|
|
||||||
state.space.raise_element(&self.window, false);
|
state.space.raise_element(&self.window, false);
|
||||||
if let WindowElement::X11(surface) = &self.window {
|
if let Some(surface) = self.window.x11_surface() {
|
||||||
state
|
// INFO: can you raise OR windows or no idk
|
||||||
.xwm
|
if !surface.is_override_redirect() {
|
||||||
.as_mut()
|
state
|
||||||
.expect("no xwm")
|
.xwm
|
||||||
.raise_window(surface)
|
.as_mut()
|
||||||
.expect("failed to raise x11 win");
|
.expect("no xwm")
|
||||||
|
.raise_window(surface)
|
||||||
|
.expect("failed to raise x11 win");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_tiled = self
|
let is_tiled = self
|
||||||
|
@ -136,12 +139,14 @@ impl PointerGrab<State> for MoveSurfaceGrab {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if let WindowElement::X11(surface) = &self.window {
|
if let Some(surface) = self.window.x11_surface() {
|
||||||
let geo = surface.geometry();
|
if !surface.is_override_redirect() {
|
||||||
let new_geo = Rectangle::from_loc_and_size(new_loc, geo.size);
|
let geo = surface.geometry();
|
||||||
surface
|
let new_geo = Rectangle::from_loc_and_size(new_loc, geo.size);
|
||||||
.configure(new_geo)
|
surface
|
||||||
.expect("failed to configure x11 win");
|
.configure(new_geo)
|
||||||
|
.expect("failed to configure x11 win");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let outputs = state.space.outputs_for_element(&self.window);
|
let outputs = state.space.outputs_for_element(&self.window);
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
desktop::space::SpaceElement,
|
desktop::{space::SpaceElement, utils::bbox_from_surface_tree, WindowSurface},
|
||||||
input::{
|
input::{
|
||||||
pointer::{AxisFrame, ButtonEvent, Focus, GrabStartData, PointerGrab, PointerInnerHandle},
|
pointer::{AxisFrame, ButtonEvent, Focus, GrabStartData, PointerGrab, PointerInnerHandle},
|
||||||
Seat, SeatHandler,
|
Seat, SeatHandler,
|
||||||
},
|
},
|
||||||
reexports::{
|
reexports::{
|
||||||
wayland_protocols::xdg::shell::server::xdg_toplevel::{self},
|
wayland_protocols::xdg::shell::server::xdg_toplevel,
|
||||||
wayland_server::protocol::wl_surface::WlSurface,
|
wayland_server::protocol::wl_surface::WlSurface,
|
||||||
},
|
},
|
||||||
utils::{IsAlive, Logical, Point, Rectangle, Size},
|
utils::{IsAlive, Logical, Point, Rectangle, Size},
|
||||||
wayland::{compositor, shell::xdg::SurfaceCachedState},
|
wayland::{compositor, seat::WaylandFocus, shell::xdg::SurfaceCachedState},
|
||||||
xwayland,
|
xwayland,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -158,28 +158,26 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
|
||||||
new_window_height.clamp(min_height, max_height),
|
new_window_height.clamp(min_height, max_height),
|
||||||
));
|
));
|
||||||
|
|
||||||
match &self.window {
|
match self.window.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
let toplevel_surface = window.toplevel().expect("in wayland enum");
|
toplevel.with_pending_state(|state| {
|
||||||
|
|
||||||
toplevel_surface.with_pending_state(|state| {
|
|
||||||
state.states.set(xdg_toplevel::State::Resizing);
|
state.states.set(xdg_toplevel::State::Resizing);
|
||||||
state.size = Some(self.last_window_size);
|
state.size = Some(self.last_window_size);
|
||||||
});
|
});
|
||||||
|
|
||||||
toplevel_surface.send_pending_configure();
|
toplevel.send_pending_configure();
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
let loc = data
|
if !surface.is_override_redirect() {
|
||||||
.space
|
let loc = data
|
||||||
.element_location(&self.window)
|
.space
|
||||||
.expect("failed to get x11 win loc");
|
.element_location(&self.window)
|
||||||
surface
|
.expect("failed to get x11 win loc");
|
||||||
.configure(Rectangle::from_loc_and_size(loc, self.last_window_size))
|
surface
|
||||||
.expect("failed to configure x11 win");
|
.configure(Rectangle::from_loc_and_size(loc, self.last_window_size))
|
||||||
|
.expect("failed to configure x11 win");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WindowElement::X11OverrideRedirect(_) => (),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,17 +206,16 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match &self.window {
|
match self.window.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
let toplevel_surface = window.toplevel().expect("in wayland enum");
|
toplevel.with_pending_state(|state| {
|
||||||
toplevel_surface.with_pending_state(|state| {
|
|
||||||
state.states.unset(xdg_toplevel::State::Resizing);
|
state.states.unset(xdg_toplevel::State::Resizing);
|
||||||
state.size = Some(self.last_window_size);
|
state.size = Some(self.last_window_size);
|
||||||
});
|
});
|
||||||
|
|
||||||
toplevel_surface.send_pending_configure();
|
toplevel.send_pending_configure();
|
||||||
|
|
||||||
toplevel_surface.wl_surface().with_state(|state| {
|
toplevel.wl_surface().with_state(|state| {
|
||||||
// TODO: validate resize state
|
// TODO: validate resize state
|
||||||
state.resize_state = ResizeSurfaceState::WaitingForLastCommit {
|
state.resize_state = ResizeSurfaceState::WaitingForLastCommit {
|
||||||
edges: self.edges,
|
edges: self.edges,
|
||||||
|
@ -226,7 +223,10 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
|
if surface.is_override_redirect() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let Some(surface) = surface.wl_surface() else { return };
|
let Some(surface) = surface.wl_surface() else { return };
|
||||||
surface.with_state(|state| {
|
surface.with_state(|state| {
|
||||||
state.resize_state = ResizeSurfaceState::WaitingForLastCommit {
|
state.resize_state = ResizeSurfaceState::WaitingForLastCommit {
|
||||||
|
@ -235,8 +235,6 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
WindowElement::X11OverrideRedirect(_) => (),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,12 +416,14 @@ pub fn handle_commit(state: &mut State, surface: &WlSurface) -> Option<()> {
|
||||||
if new_loc.x.is_some() || new_loc.y.is_some() {
|
if new_loc.x.is_some() || new_loc.y.is_some() {
|
||||||
state.space.map_element(window.clone(), window_loc, false);
|
state.space.map_element(window.clone(), window_loc, false);
|
||||||
|
|
||||||
if let WindowElement::X11(surface) = window {
|
if let Some(surface) = window.x11_surface() {
|
||||||
let geo = surface.geometry();
|
if !surface.is_override_redirect() {
|
||||||
let new_geo = Rectangle::from_loc_and_size(window_loc, geo.size);
|
let geo = surface.geometry();
|
||||||
surface
|
let new_geo = Rectangle::from_loc_and_size(window_loc, geo.size);
|
||||||
.configure(new_geo)
|
surface
|
||||||
.expect("failed to configure x11 win");
|
.configure(new_geo)
|
||||||
|
.expect("failed to configure x11 win");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,18 +458,14 @@ pub fn resize_request_client(
|
||||||
.expect("resize request called on unmapped window");
|
.expect("resize request called on unmapped window");
|
||||||
let initial_window_size = window.geometry().size;
|
let initial_window_size = window.geometry().size;
|
||||||
|
|
||||||
if let Some(WindowElement::Wayland(window)) = state.window_for_surface(surface) {
|
if let Some(window) = state.window_for_surface(surface) {
|
||||||
window
|
if let Some(toplevel) = window.toplevel() {
|
||||||
.toplevel()
|
toplevel.with_pending_state(|state| {
|
||||||
.expect("in wayland enum")
|
|
||||||
.with_pending_state(|state| {
|
|
||||||
state.states.set(xdg_toplevel::State::Resizing);
|
state.states.set(xdg_toplevel::State::Resizing);
|
||||||
});
|
});
|
||||||
|
|
||||||
window
|
toplevel.send_pending_configure();
|
||||||
.toplevel()
|
}
|
||||||
.expect("in wayland enum")
|
|
||||||
.send_pending_configure();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let grab = ResizeSurfaceGrab::start(
|
let grab = ResizeSurfaceGrab::start(
|
||||||
|
@ -512,18 +508,14 @@ pub fn resize_request_server(
|
||||||
.expect("resize request called on unmapped window");
|
.expect("resize request called on unmapped window");
|
||||||
let initial_window_size = window.geometry().size;
|
let initial_window_size = window.geometry().size;
|
||||||
|
|
||||||
if let Some(WindowElement::Wayland(window)) = state.window_for_surface(surface) {
|
if let Some(window) = state.window_for_surface(surface) {
|
||||||
window
|
if let Some(toplevel) = window.toplevel() {
|
||||||
.toplevel()
|
toplevel.with_pending_state(|state| {
|
||||||
.expect("in wayland enum")
|
|
||||||
.with_pending_state(|state| {
|
|
||||||
state.states.set(xdg_toplevel::State::Resizing);
|
state.states.set(xdg_toplevel::State::Resizing);
|
||||||
});
|
});
|
||||||
|
|
||||||
window
|
toplevel.send_pending_configure();
|
||||||
.toplevel()
|
}
|
||||||
.expect("in wayland enum")
|
|
||||||
.send_pending_configure();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let start_data = smithay::input::pointer::GrabStartData {
|
let start_data = smithay::input::pointer::GrabStartData {
|
||||||
|
|
|
@ -60,7 +60,6 @@ use smithay::{
|
||||||
use crate::{
|
use crate::{
|
||||||
focus::FocusTarget,
|
focus::FocusTarget,
|
||||||
state::{ClientState, State, WithState},
|
state::{ClientState, State, WithState},
|
||||||
window::WindowElement,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl BufferHandler for State {
|
impl BufferHandler for State {
|
||||||
|
@ -107,9 +106,10 @@ impl CompositorHandler for State {
|
||||||
fn commit(&mut self, surface: &WlSurface) {
|
fn commit(&mut self, surface: &WlSurface) {
|
||||||
tracing::trace!("commit on surface {surface:?}");
|
tracing::trace!("commit on surface {surface:?}");
|
||||||
|
|
||||||
|
utils::on_commit_buffer_handler::<State>(surface);
|
||||||
|
|
||||||
X11Wm::commit_hook::<State>(surface);
|
X11Wm::commit_hook::<State>(surface);
|
||||||
|
|
||||||
utils::on_commit_buffer_handler::<State>(surface);
|
|
||||||
self.backend.early_import(surface);
|
self.backend.early_import(surface);
|
||||||
|
|
||||||
let mut root = surface.clone();
|
let mut root = surface.clone();
|
||||||
|
@ -118,10 +118,10 @@ impl CompositorHandler for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !compositor::is_sync_subsurface(surface) {
|
if !compositor::is_sync_subsurface(surface) {
|
||||||
if let Some(win @ WindowElement::Wayland(window)) = &self.window_for_surface(&root) {
|
if let Some(window) = self.window_for_surface(&root) {
|
||||||
window.on_commit();
|
window.on_commit();
|
||||||
if let Some(loc) = win.with_state(|state| state.target_loc.take()) {
|
if let Some(loc) = window.with_state(|state| state.target_loc.take()) {
|
||||||
self.space.map_element(win.clone(), loc, false);
|
self.space.map_element(window.clone(), loc, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -149,7 +149,7 @@ impl CompositorHandler for State {
|
||||||
self.output_focus_stack.current_focus(),
|
self.output_focus_stack.current_focus(),
|
||||||
self.space.outputs().next(),
|
self.space.outputs().next(),
|
||||||
) {
|
) {
|
||||||
tracing::debug!("PLACING TOPLEVEL");
|
tracing::debug!("Placing toplevel");
|
||||||
new_window.place_on_output(output);
|
new_window.place_on_output(output);
|
||||||
output.with_state(|state| state.focus_stack.set_focus(new_window.clone()));
|
output.with_state(|state| state.focus_stack.set_focus(new_window.clone()));
|
||||||
}
|
}
|
||||||
|
@ -180,22 +180,9 @@ impl CompositorHandler for State {
|
||||||
SERIAL_COUNTER.next_serial(),
|
SERIAL_COUNTER.next_serial(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else if let WindowElement::Wayland(window) = &new_window {
|
} else if new_window.toplevel().is_some() {
|
||||||
window.on_commit();
|
new_window.on_commit();
|
||||||
let initial_configure_sent = compositor::with_states(surface, |states| {
|
ensure_initial_configure(surface, self);
|
||||||
states
|
|
||||||
.data_map
|
|
||||||
.get::<XdgToplevelSurfaceData>()
|
|
||||||
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
|
|
||||||
.lock()
|
|
||||||
.expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
|
|
||||||
.initial_configure_sent
|
|
||||||
});
|
|
||||||
|
|
||||||
if !initial_configure_sent {
|
|
||||||
tracing::debug!("Initial configure");
|
|
||||||
window.toplevel().expect("in wayland enum").send_configure();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -266,8 +253,11 @@ impl CompositorHandler for State {
|
||||||
delegate_compositor!(State);
|
delegate_compositor!(State);
|
||||||
|
|
||||||
fn ensure_initial_configure(surface: &WlSurface, state: &mut State) {
|
fn ensure_initial_configure(surface: &WlSurface, state: &mut State) {
|
||||||
if let Some(window) = state.window_for_surface(surface) {
|
if let (Some(window), _) | (None, Some(window)) = (
|
||||||
if let WindowElement::Wayland(window) = &window {
|
state.window_for_surface(surface),
|
||||||
|
state.new_window_for_surface(surface),
|
||||||
|
) {
|
||||||
|
if let Some(toplevel) = window.toplevel() {
|
||||||
let initial_configure_sent = compositor::with_states(surface, |states| {
|
let initial_configure_sent = compositor::with_states(surface, |states| {
|
||||||
states
|
states
|
||||||
.data_map
|
.data_map
|
||||||
|
@ -280,7 +270,7 @@ fn ensure_initial_configure(surface: &WlSurface, state: &mut State) {
|
||||||
|
|
||||||
if !initial_configure_sent {
|
if !initial_configure_sent {
|
||||||
tracing::debug!("Initial configure");
|
tracing::debug!("Initial configure");
|
||||||
window.toplevel().expect("in wayland enum").send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -17,8 +17,11 @@ use smithay::{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
utils::{Logical, Point, Rectangle, Serial, SERIAL_COUNTER},
|
utils::{Logical, Point, Rectangle, Serial, SERIAL_COUNTER},
|
||||||
wayland::shell::xdg::{
|
wayland::{
|
||||||
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
|
seat::WaylandFocus,
|
||||||
|
shell::xdg::{
|
||||||
|
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,65 +44,8 @@ impl XdgShellHandler for State {
|
||||||
state.states.set(xdg_toplevel::State::TiledRight);
|
state.states.set(xdg_toplevel::State::TiledRight);
|
||||||
});
|
});
|
||||||
|
|
||||||
let window = WindowElement::Wayland(Window::new_wayland_window(surface.clone()));
|
let window = WindowElement::new(Window::new_wayland_window(surface.clone()));
|
||||||
self.new_windows.push(window);
|
self.new_windows.push(window);
|
||||||
|
|
||||||
// if let (Some(output), _) | (None, Some(output)) = (
|
|
||||||
// &self.focus_state.focused_output,
|
|
||||||
// self.space.outputs().next(),
|
|
||||||
// ) {
|
|
||||||
// tracing::debug!("PLACING TOPLEVEL");
|
|
||||||
// window.place_on_output(output);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // note to self: don't reorder this
|
|
||||||
// // TODO: fix it so that reordering this doesn't break stuff
|
|
||||||
// self.windows.push(window.clone());
|
|
||||||
//
|
|
||||||
// self.space.map_element(window.clone(), (0, 0), true);
|
|
||||||
//
|
|
||||||
// let win_clone = window.clone();
|
|
||||||
//
|
|
||||||
// // Let the initial configure happen before updating the windows
|
|
||||||
// self.schedule(
|
|
||||||
// move |_data| {
|
|
||||||
// if let WindowElement::Wayland(window) = &win_clone {
|
|
||||||
// let initial_configure_sent =
|
|
||||||
// compositor::with_states(window.toplevel().wl_surface(), |states| {
|
|
||||||
// states
|
|
||||||
// .data_map
|
|
||||||
// .get::<smithay::wayland::shell::xdg::XdgToplevelSurfaceData>()
|
|
||||||
// .expect("XdgToplevelSurfaceData wasn't in surface's data map")
|
|
||||||
// .lock()
|
|
||||||
// .expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
|
|
||||||
// .initial_configure_sent
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// initial_configure_sent
|
|
||||||
// } else {
|
|
||||||
// true
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// |data| {
|
|
||||||
// data.state.apply_window_rules(&window);
|
|
||||||
//
|
|
||||||
// if let Some(focused_output) = data.state.focus_state.focused_output.clone() {
|
|
||||||
// data.state.update_windows(&focused_output);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// data.state.loop_handle.insert_idle(move |data| {
|
|
||||||
// data.state
|
|
||||||
// .seat
|
|
||||||
// .get_keyboard()
|
|
||||||
// .expect("Seat had no keyboard") // FIXME: actually handle error
|
|
||||||
// .set_focus(
|
|
||||||
// &mut data.state,
|
|
||||||
// Some(FocusTarget::Window(window)),
|
|
||||||
// SERIAL_COUNTER.next_serial(),
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toplevel_destroyed(&mut self, surface: ToplevelSurface) {
|
fn toplevel_destroyed(&mut self, surface: ToplevelSurface) {
|
||||||
|
@ -138,8 +84,8 @@ impl XdgShellHandler for State {
|
||||||
// TODO:
|
// TODO:
|
||||||
self.space.raise_element(win, true);
|
self.space.raise_element(win, true);
|
||||||
self.z_index_stack.set_focus(win.clone());
|
self.z_index_stack.set_focus(win.clone());
|
||||||
if let WindowElement::Wayland(win) = &win {
|
if let Some(toplevel) = win.toplevel() {
|
||||||
win.toplevel().expect("in wayland enum").send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.seat
|
self.seat
|
||||||
|
@ -733,27 +679,6 @@ impl XdgShellHandler for State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn ack_configure(&mut self, surface: WlSurface, configure: Configure) {
|
|
||||||
// if let Some(window) = self.window_for_surface(&surface) {
|
|
||||||
// if let LocationRequestState::Requested(serial, new_loc) =
|
|
||||||
// window.with_state(|state| state.loc_request_state.clone())
|
|
||||||
// {
|
|
||||||
// match &configure {
|
|
||||||
// Configure::Toplevel(configure) => {
|
|
||||||
// if configure.serial >= serial {
|
|
||||||
// tracing::debug!("acked configure, new loc is {:?}", new_loc);
|
|
||||||
// window.with_state(|state| {
|
|
||||||
// state.loc_request_state =
|
|
||||||
// LocationRequestState::Acknowledged(new_loc);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Configure::Popup(_) => todo!(),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn fullscreen_request(&mut self, surface: ToplevelSurface, mut wl_output: Option<WlOutput>) {
|
fn fullscreen_request(&mut self, surface: ToplevelSurface, mut wl_output: Option<WlOutput>) {
|
||||||
if !surface
|
if !surface
|
||||||
.current_state()
|
.current_state()
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
|
desktop::Window,
|
||||||
utils::{Logical, Point, Rectangle, SERIAL_COUNTER},
|
utils::{Logical, Point, Rectangle, SERIAL_COUNTER},
|
||||||
wayland::{
|
wayland::{
|
||||||
selection::data_device::{
|
seat::WaylandFocus,
|
||||||
clear_data_device_selection, current_data_device_selection_userdata,
|
|
||||||
request_data_device_client_selection, set_data_device_selection,
|
|
||||||
},
|
|
||||||
selection::{
|
selection::{
|
||||||
|
data_device::{
|
||||||
|
clear_data_device_selection, current_data_device_selection_userdata,
|
||||||
|
request_data_device_client_selection, set_data_device_selection,
|
||||||
|
},
|
||||||
primary_selection::{
|
primary_selection::{
|
||||||
clear_primary_selection, current_primary_selection_userdata,
|
clear_primary_selection, current_primary_selection_userdata,
|
||||||
request_primary_client_selection, set_primary_selection,
|
request_primary_client_selection, set_primary_selection,
|
||||||
|
@ -36,12 +38,12 @@ impl XwmHandler for State {
|
||||||
|
|
||||||
fn new_override_redirect_window(&mut self, _xwm: XwmId, _window: X11Surface) {}
|
fn new_override_redirect_window(&mut self, _xwm: XwmId, _window: X11Surface) {}
|
||||||
|
|
||||||
fn map_window_request(&mut self, _xwm: XwmId, window: X11Surface) {
|
fn map_window_request(&mut self, _xwm: XwmId, surface: X11Surface) {
|
||||||
tracing::trace!("map_window_request");
|
tracing::trace!("map_window_request");
|
||||||
|
|
||||||
assert!(!window.is_override_redirect());
|
assert!(!surface.is_override_redirect());
|
||||||
|
|
||||||
let window = WindowElement::X11(window);
|
let window = WindowElement::new(Window::new_x11_window(surface));
|
||||||
self.space.map_element(window.clone(), (0, 0), true);
|
self.space.map_element(window.clone(), (0, 0), true);
|
||||||
let bbox = self
|
let bbox = self
|
||||||
.space
|
.space
|
||||||
|
@ -70,7 +72,7 @@ impl XwmHandler for State {
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let WindowElement::X11(surface) = &window else {
|
let Some(surface) = window.x11_surface() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,14 +124,14 @@ impl XwmHandler for State {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mapped_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) {
|
fn mapped_override_redirect_window(&mut self, _xwm: XwmId, surface: X11Surface) {
|
||||||
tracing::trace!("mapped_override_redirect_window");
|
tracing::trace!("mapped_override_redirect_window");
|
||||||
|
|
||||||
assert!(window.is_override_redirect());
|
assert!(surface.is_override_redirect());
|
||||||
|
|
||||||
let loc = window.geometry().loc;
|
let loc = surface.geometry().loc;
|
||||||
|
|
||||||
let window = WindowElement::X11OverrideRedirect(window);
|
let window = WindowElement::new(Window::new_x11_window(surface));
|
||||||
|
|
||||||
self.windows.push(window.clone());
|
self.windows.push(window.clone());
|
||||||
self.z_index_stack.set_focus(window.clone());
|
self.z_index_stack.set_focus(window.clone());
|
||||||
|
@ -139,18 +141,20 @@ impl XwmHandler for State {
|
||||||
self.space.outputs().next(),
|
self.space.outputs().next(),
|
||||||
) {
|
) {
|
||||||
window.place_on_output(output);
|
window.place_on_output(output);
|
||||||
|
// FIXME: setting focus here may possibly muck things up
|
||||||
|
// | or maybe they won't idk
|
||||||
output.with_state(|state| state.focus_stack.set_focus(window.clone()))
|
output.with_state(|state| state.focus_stack.set_focus(window.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.space.map_element(window, loc, true);
|
self.space.map_element(window, loc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unmapped_window(&mut self, _xwm: XwmId, window: X11Surface) {
|
fn unmapped_window(&mut self, _xwm: XwmId, surface: X11Surface) {
|
||||||
for output in self.space.outputs() {
|
for output in self.space.outputs() {
|
||||||
output.with_state(|state| {
|
output.with_state(|state| {
|
||||||
state.focus_stack.stack.retain(|win| {
|
state.focus_stack.stack.retain(|win| {
|
||||||
win.wl_surface()
|
win.wl_surface()
|
||||||
.is_some_and(|surf| Some(surf) != window.wl_surface())
|
.is_some_and(|surf| Some(surf) != surface.wl_surface())
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -158,7 +162,7 @@ impl XwmHandler for State {
|
||||||
let win = self
|
let win = self
|
||||||
.space
|
.space
|
||||||
.elements()
|
.elements()
|
||||||
.find(|elem| matches!(elem, WindowElement::X11(surface) if surface == &window))
|
.find(|elem| matches!(elem.x11_surface(), Some(surf) if surf == &surface))
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
||||||
if let Some(win) = win {
|
if let Some(win) = win {
|
||||||
|
@ -178,8 +182,8 @@ impl XwmHandler for State {
|
||||||
if let Some(FocusTarget::Window(win)) = &focus {
|
if let Some(FocusTarget::Window(win)) = &focus {
|
||||||
self.space.raise_element(win, true);
|
self.space.raise_element(win, true);
|
||||||
self.z_index_stack.set_focus(win.clone());
|
self.z_index_stack.set_focus(win.clone());
|
||||||
if let WindowElement::Wayland(win) = &win {
|
if let Some(toplevel) = win.toplevel() {
|
||||||
win.toplevel().expect("in wayland enum").send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,18 +196,18 @@ impl XwmHandler for State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !window.is_override_redirect() {
|
if !surface.is_override_redirect() {
|
||||||
tracing::debug!("set mapped to false");
|
tracing::debug!("set mapped to false");
|
||||||
window.set_mapped(false).expect("failed to unmap x11 win");
|
surface.set_mapped(false).expect("failed to unmap x11 win");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn destroyed_window(&mut self, _xwm: XwmId, window: X11Surface) {
|
fn destroyed_window(&mut self, _xwm: XwmId, surface: X11Surface) {
|
||||||
for output in self.space.outputs() {
|
for output in self.space.outputs() {
|
||||||
output.with_state(|state| {
|
output.with_state(|state| {
|
||||||
state.focus_stack.stack.retain(|win| {
|
state.focus_stack.stack.retain(|win| {
|
||||||
win.wl_surface()
|
win.wl_surface()
|
||||||
.is_some_and(|surf| Some(surf) != window.wl_surface())
|
.is_some_and(|surf| Some(surf) != surface.wl_surface())
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -213,10 +217,8 @@ impl XwmHandler for State {
|
||||||
.iter()
|
.iter()
|
||||||
.find(|elem| {
|
.find(|elem| {
|
||||||
matches!(
|
matches!(
|
||||||
elem,
|
elem.x11_surface(),
|
||||||
WindowElement::X11(surface)
|
Some(surf) if surf.wl_surface() == surface.wl_surface()
|
||||||
| WindowElement::X11OverrideRedirect(surface)
|
|
||||||
if surface.wl_surface() == window.wl_surface()
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.cloned();
|
.cloned();
|
||||||
|
@ -241,8 +243,8 @@ impl XwmHandler for State {
|
||||||
if let Some(FocusTarget::Window(win)) = &focus {
|
if let Some(FocusTarget::Window(win)) = &focus {
|
||||||
self.space.raise_element(win, true);
|
self.space.raise_element(win, true);
|
||||||
self.z_index_stack.set_focus(win.clone());
|
self.z_index_stack.set_focus(win.clone());
|
||||||
if let WindowElement::Wayland(win) = &win {
|
if let Some(toplevel) = win.toplevel() {
|
||||||
win.toplevel().expect("in wayland enum").send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,14 +285,14 @@ impl XwmHandler for State {
|
||||||
fn configure_notify(
|
fn configure_notify(
|
||||||
&mut self,
|
&mut self,
|
||||||
_xwm: XwmId,
|
_xwm: XwmId,
|
||||||
window: X11Surface,
|
surface: X11Surface,
|
||||||
geometry: Rectangle<i32, Logical>,
|
geometry: Rectangle<i32, Logical>,
|
||||||
_above: Option<smithay::reexports::x11rb::protocol::xproto::Window>,
|
_above: Option<smithay::reexports::x11rb::protocol::xproto::Window>,
|
||||||
) {
|
) {
|
||||||
let Some(win) = self
|
let Some(win) = self
|
||||||
.space
|
.space
|
||||||
.elements()
|
.elements()
|
||||||
.find(|elem| matches!(elem, WindowElement::X11(surface) if surface == &window))
|
.find(|elem| matches!(elem.x11_surface(), Some(surf) if surf == &surface))
|
||||||
.cloned()
|
.cloned()
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
|
@ -409,11 +411,12 @@ impl XwmHandler for State {
|
||||||
.get_keyboard()
|
.get_keyboard()
|
||||||
.and_then(|kb| kb.current_focus())
|
.and_then(|kb| kb.current_focus())
|
||||||
.is_some_and(|focus| {
|
.is_some_and(|focus| {
|
||||||
if let FocusTarget::Window(WindowElement::X11(surface)) = focus {
|
if let FocusTarget::Window(window) = focus {
|
||||||
surface.xwm_id().expect("x11surface had no xwm id") == xwm
|
if let Some(surface) = window.x11_surface() {
|
||||||
} else {
|
return surface.xwm_id().expect("x11surface had no xwm id") == xwm;
|
||||||
false
|
}
|
||||||
}
|
}
|
||||||
|
false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
src/input.rs
12
src/input.rs
|
@ -4,7 +4,7 @@ pub mod libinput;
|
||||||
|
|
||||||
use std::{collections::HashMap, mem::Discriminant};
|
use std::{collections::HashMap, mem::Discriminant};
|
||||||
|
|
||||||
use crate::{focus::FocusTarget, state::WithState, window::WindowElement};
|
use crate::{focus::FocusTarget, state::WithState};
|
||||||
use pinnacle_api_defs::pinnacle::input::v0alpha1::{
|
use pinnacle_api_defs::pinnacle::input::v0alpha1::{
|
||||||
set_libinput_setting_request::Setting, set_mousebind_request, SetKeybindResponse,
|
set_libinput_setting_request::Setting, set_mousebind_request, SetKeybindResponse,
|
||||||
SetMousebindResponse,
|
SetMousebindResponse,
|
||||||
|
@ -351,14 +351,14 @@ impl State {
|
||||||
|
|
||||||
if !matches!(
|
if !matches!(
|
||||||
&focus,
|
&focus,
|
||||||
FocusTarget::Window(WindowElement::X11OverrideRedirect(_))
|
FocusTarget::Window(window) if window.is_x11_override_redirect()
|
||||||
) {
|
) {
|
||||||
keyboard.set_focus(self, Some(focus.clone()), serial);
|
keyboard.set_focus(self, Some(focus.clone()), serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
for window in self.space.elements() {
|
for window in self.space.elements() {
|
||||||
if let WindowElement::Wayland(window) = window {
|
if let Some(toplevel) = window.toplevel() {
|
||||||
window.toplevel().expect("in wayland enum").send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -367,8 +367,8 @@ impl State {
|
||||||
state.focus_stack.unset_focus();
|
state.focus_stack.unset_focus();
|
||||||
for window in state.focus_stack.stack.iter() {
|
for window in state.focus_stack.stack.iter() {
|
||||||
window.set_activate(false);
|
window.set_activate(false);
|
||||||
if let WindowElement::Wayland(window) = window {
|
if let Some(toplevel) = window.toplevel() {
|
||||||
window.toplevel().expect("in wayland enum").send_configure();
|
toplevel.send_configure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
desktop::layer_map_for_output,
|
desktop::{layer_map_for_output, WindowSurface},
|
||||||
output::Output,
|
output::Output,
|
||||||
utils::{Logical, Point, Rectangle, Serial, Size},
|
utils::{Logical, Point, Rectangle, Serial, Size},
|
||||||
wayland::{compositor, shell::xdg::XdgToplevelSurfaceData},
|
wayland::{compositor, shell::xdg::XdgToplevelSurfaceData},
|
||||||
|
@ -115,26 +115,20 @@ impl State {
|
||||||
|
|
||||||
for win in windows_on_foc_tags.iter() {
|
for win in windows_on_foc_tags.iter() {
|
||||||
if win.with_state(|state| state.target_loc.is_some()) {
|
if win.with_state(|state| state.target_loc.is_some()) {
|
||||||
match win {
|
match win.underlying_surface() {
|
||||||
WindowElement::Wayland(wl_win) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
let pending = compositor::with_states(
|
let pending = compositor::with_states(toplevel.wl_surface(), |states| {
|
||||||
wl_win.toplevel().expect("in wayland enum").wl_surface(),
|
states
|
||||||
|states| {
|
.data_map
|
||||||
states
|
.get::<XdgToplevelSurfaceData>()
|
||||||
.data_map
|
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
|
||||||
.get::<XdgToplevelSurfaceData>()
|
.lock()
|
||||||
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
|
.expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
|
||||||
.lock()
|
.has_pending_changes()
|
||||||
.expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
|
});
|
||||||
.has_pending_changes()
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if pending {
|
if pending {
|
||||||
pending_wins.push((
|
pending_wins.push((win.clone(), toplevel.send_configure()))
|
||||||
win.clone(),
|
|
||||||
wl_win.toplevel().expect("in wayland enum").send_configure(),
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
let loc = win.with_state(|state| state.target_loc.take());
|
let loc = win.with_state(|state| state.target_loc.take());
|
||||||
if let Some(loc) = loc {
|
if let Some(loc) = loc {
|
||||||
|
@ -142,14 +136,12 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowElement::X11(_) => {
|
WindowSurface::X11(_) => {
|
||||||
let loc = win.with_state(|state| state.target_loc.take());
|
let loc = win.with_state(|state| state.target_loc.take());
|
||||||
if let Some(loc) = loc {
|
if let Some(loc) = loc {
|
||||||
self.space.map_element(win.clone(), loc, false);
|
self.space.map_element(win.clone(), loc, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowElement::X11OverrideRedirect(_) => (),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::{ops::Deref, sync::Mutex};
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::renderer::{
|
backend::renderer::{
|
||||||
|
@ -71,18 +71,8 @@ where
|
||||||
scale: Scale<f64>,
|
scale: Scale<f64>,
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Vec<C> {
|
) -> Vec<C> {
|
||||||
match self {
|
self.deref()
|
||||||
WindowElement::Wayland(window) => {
|
.render_elements(renderer, location, scale, alpha)
|
||||||
window.render_elements(renderer, location, scale, alpha)
|
|
||||||
}
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
surface.render_elements(renderer, location, scale, alpha)
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
.into_iter()
|
|
||||||
.map(C::from)
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,10 +297,8 @@ where
|
||||||
|
|
||||||
let top_fullscreen_window = windows.iter().rev().find(|win| {
|
let top_fullscreen_window = windows.iter().rev().find(|win| {
|
||||||
let is_wayland_actually_fullscreen = {
|
let is_wayland_actually_fullscreen = {
|
||||||
if let WindowElement::Wayland(window) = win {
|
if let Some(toplevel) = win.toplevel() {
|
||||||
window
|
toplevel
|
||||||
.toplevel()
|
|
||||||
.expect("in wayland enum")
|
|
||||||
.current_state()
|
.current_state()
|
||||||
.states
|
.states
|
||||||
.contains(xdg_toplevel::State::Fullscreen)
|
.contains(xdg_toplevel::State::Fullscreen)
|
||||||
|
|
451
src/window.rs
451
src/window.rs
|
@ -2,40 +2,23 @@
|
||||||
|
|
||||||
pub mod rules;
|
pub mod rules;
|
||||||
|
|
||||||
use std::{cell::RefCell, time::Duration};
|
use std::{cell::RefCell, ops::Deref};
|
||||||
|
|
||||||
use pinnacle_api_defs::pinnacle::signal::v0alpha1::{
|
use pinnacle_api_defs::pinnacle::signal::v0alpha1::{
|
||||||
WindowPointerEnterResponse, WindowPointerLeaveResponse,
|
WindowPointerEnterResponse, WindowPointerLeaveResponse,
|
||||||
};
|
};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::input::KeyState,
|
backend::input::KeyState,
|
||||||
desktop::{
|
desktop::{space::SpaceElement, Window, WindowSurface},
|
||||||
utils::{
|
|
||||||
send_dmabuf_feedback_surface_tree, send_frames_surface_tree,
|
|
||||||
take_presentation_feedback_surface_tree, with_surfaces_surface_tree,
|
|
||||||
OutputPresentationFeedback,
|
|
||||||
},
|
|
||||||
Window,
|
|
||||||
},
|
|
||||||
input::{
|
input::{
|
||||||
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
|
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
|
||||||
pointer::{AxisFrame, MotionEvent, PointerTarget},
|
pointer::{AxisFrame, MotionEvent, PointerTarget},
|
||||||
Seat,
|
Seat,
|
||||||
},
|
},
|
||||||
output::Output,
|
output::Output,
|
||||||
reexports::{
|
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||||
wayland_protocols::wp::presentation_time::server::wp_presentation_feedback,
|
utils::{IsAlive, Logical, Point, Rectangle, Serial},
|
||||||
wayland_server::protocol::wl_surface::WlSurface,
|
wayland::{compositor, seat::WaylandFocus, shell::xdg::XdgToplevelSurfaceData},
|
||||||
},
|
|
||||||
space_elements,
|
|
||||||
utils::{user_data::UserDataMap, Logical, Rectangle, Serial},
|
|
||||||
wayland::{
|
|
||||||
compositor::{self, SurfaceData},
|
|
||||||
dmabuf::DmabufFeedback,
|
|
||||||
seat::WaylandFocus,
|
|
||||||
shell::xdg::XdgToplevelSurfaceData,
|
|
||||||
},
|
|
||||||
xwayland::X11Surface,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::state::{State, WithState};
|
use crate::state::{State, WithState};
|
||||||
|
@ -44,143 +27,20 @@ use self::window_state::WindowElementState;
|
||||||
|
|
||||||
pub mod window_state;
|
pub mod window_state;
|
||||||
|
|
||||||
space_elements! {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
/// The different types of windows.
|
pub struct WindowElement(Window);
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub WindowElement;
|
impl Deref for WindowElement {
|
||||||
/// This is a native Wayland window.
|
type Target = Window;
|
||||||
Wayland = Window,
|
|
||||||
/// This is an Xwayland window.
|
fn deref(&self) -> &Self::Target {
|
||||||
X11 = X11Surface,
|
&self.0
|
||||||
/// This is an Xwayland override redirect window, which should not be messed with.
|
}
|
||||||
X11OverrideRedirect = X11Surface,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowElement {
|
impl WindowElement {
|
||||||
pub fn with_surfaces<F>(&self, processor: F)
|
pub fn new(window: Window) -> Self {
|
||||||
where
|
Self(window)
|
||||||
F: FnMut(&WlSurface, &SurfaceData) + Copy,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
WindowElement::Wayland(window) => window.with_surfaces(processor),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
if let Some(surface) = surface.wl_surface() {
|
|
||||||
with_surfaces_surface_tree(&surface, processor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_frame<T, F>(
|
|
||||||
&self,
|
|
||||||
output: &Output,
|
|
||||||
time: T,
|
|
||||||
throttle: Option<Duration>,
|
|
||||||
primary_scan_out_output: F,
|
|
||||||
) where
|
|
||||||
T: Into<Duration>,
|
|
||||||
F: FnMut(&WlSurface, &SurfaceData) -> Option<Output> + Copy,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
WindowElement::Wayland(window) => {
|
|
||||||
window.send_frame(output, time, throttle, primary_scan_out_output)
|
|
||||||
}
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
if let Some(surface) = surface.wl_surface() {
|
|
||||||
send_frames_surface_tree(
|
|
||||||
&surface,
|
|
||||||
output,
|
|
||||||
time,
|
|
||||||
throttle,
|
|
||||||
primary_scan_out_output,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_dmabuf_feedback<'a, P, F>(
|
|
||||||
&self,
|
|
||||||
output: &Output,
|
|
||||||
primary_scan_out_output: P,
|
|
||||||
select_dmabuf_feedback: F,
|
|
||||||
) where
|
|
||||||
P: FnMut(&WlSurface, &SurfaceData) -> Option<Output> + Copy,
|
|
||||||
F: Fn(&WlSurface, &SurfaceData) -> &'a DmabufFeedback + Copy,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
WindowElement::Wayland(window) => {
|
|
||||||
window.send_dmabuf_feedback(
|
|
||||||
output,
|
|
||||||
primary_scan_out_output,
|
|
||||||
select_dmabuf_feedback,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
if let Some(surface) = surface.wl_surface() {
|
|
||||||
send_dmabuf_feedback_surface_tree(
|
|
||||||
&surface,
|
|
||||||
output,
|
|
||||||
primary_scan_out_output,
|
|
||||||
select_dmabuf_feedback,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn take_presentation_feedback<F1, F2>(
|
|
||||||
&self,
|
|
||||||
output_feedback: &mut OutputPresentationFeedback,
|
|
||||||
primary_scan_out_output: F1,
|
|
||||||
presentation_feedback_flags: F2,
|
|
||||||
) where
|
|
||||||
F1: FnMut(&WlSurface, &SurfaceData) -> Option<Output> + Copy,
|
|
||||||
F2: FnMut(&WlSurface, &SurfaceData) -> wp_presentation_feedback::Kind + Copy,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
WindowElement::Wayland(window) => {
|
|
||||||
window.take_presentation_feedback(
|
|
||||||
output_feedback,
|
|
||||||
primary_scan_out_output,
|
|
||||||
presentation_feedback_flags,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
if let Some(surface) = surface.wl_surface() {
|
|
||||||
take_presentation_feedback_surface_tree(
|
|
||||||
&surface,
|
|
||||||
output_feedback,
|
|
||||||
primary_scan_out_output,
|
|
||||||
presentation_feedback_flags,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wl_surface(&self) -> Option<WlSurface> {
|
|
||||||
match self {
|
|
||||||
WindowElement::Wayland(window) => window.wl_surface(),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
surface.wl_surface()
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn user_data(&self) -> &UserDataMap {
|
|
||||||
match self {
|
|
||||||
WindowElement::Wayland(window) => window.user_data(),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
surface.user_data()
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a geometry change without mapping windows or sending
|
/// Send a geometry change without mapping windows or sending
|
||||||
|
@ -191,16 +51,13 @@ impl WindowElement {
|
||||||
/// RefCell Safety: This method uses a [`RefCell`] on this window.
|
/// RefCell Safety: This method uses a [`RefCell`] on this window.
|
||||||
// TODO: ^ does that make things flicker?
|
// TODO: ^ does that make things flicker?
|
||||||
pub fn change_geometry(&self, new_geo: Rectangle<i32, Logical>) {
|
pub fn change_geometry(&self, new_geo: Rectangle<i32, Logical>) {
|
||||||
match self {
|
match self.0.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
window
|
toplevel.with_pending_state(|state| {
|
||||||
.toplevel()
|
state.size = Some(new_geo.size);
|
||||||
.expect("in wayland enum")
|
});
|
||||||
.with_pending_state(|state| {
|
|
||||||
state.size = Some(new_geo.size);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
// TODO: maybe move this check elsewhere idk
|
// TODO: maybe move this check elsewhere idk
|
||||||
if !surface.is_override_redirect() {
|
if !surface.is_override_redirect() {
|
||||||
surface
|
surface
|
||||||
|
@ -208,21 +65,16 @@ impl WindowElement {
|
||||||
.expect("failed to configure x11 win");
|
.expect("failed to configure x11 win");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
self.with_state(|state| {
|
self.with_state(|state| {
|
||||||
state.target_loc = Some(new_geo.loc);
|
state.target_loc = Some(new_geo.loc);
|
||||||
});
|
});
|
||||||
// self.with_state(|state| {
|
|
||||||
// state.loc_request_state = LocationRequestState::Sent(new_geo.loc);
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn class(&self) -> Option<String> {
|
pub fn class(&self) -> Option<String> {
|
||||||
match self {
|
match self.0.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => compositor::with_states(
|
WindowSurface::Wayland(toplevel) => {
|
||||||
window.toplevel().expect("in wayland enum").wl_surface(),
|
compositor::with_states(toplevel.wl_surface(), |states| {
|
||||||
|states| {
|
|
||||||
states
|
states
|
||||||
.data_map
|
.data_map
|
||||||
.get::<XdgToplevelSurfaceData>()
|
.get::<XdgToplevelSurfaceData>()
|
||||||
|
@ -231,20 +83,16 @@ impl WindowElement {
|
||||||
.expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
|
.expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
|
||||||
.app_id
|
.app_id
|
||||||
.clone()
|
.clone()
|
||||||
},
|
})
|
||||||
),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
Some(surface.class())
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
WindowSurface::X11(surface) => Some(surface.class()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn title(&self) -> Option<String> {
|
pub fn title(&self) -> Option<String> {
|
||||||
match self {
|
match self.0.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => compositor::with_states(
|
WindowSurface::Wayland(toplevel) => {
|
||||||
window.toplevel().expect("in wayland enum").wl_surface(),
|
compositor::with_states(toplevel.wl_surface(), |states| {
|
||||||
|states| {
|
|
||||||
states
|
states
|
||||||
.data_map
|
.data_map
|
||||||
.get::<XdgToplevelSurfaceData>()
|
.get::<XdgToplevelSurfaceData>()
|
||||||
|
@ -253,12 +101,9 @@ impl WindowElement {
|
||||||
.expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
|
.expect("Failed to lock Mutex<XdgToplevelSurfaceData>")
|
||||||
.title
|
.title
|
||||||
.clone()
|
.clone()
|
||||||
},
|
})
|
||||||
),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
Some(surface.title())
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
WindowSurface::X11(surface) => Some(surface.title()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,58 +157,67 @@ impl WindowElement {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the window element is [`Wayland`].
|
|
||||||
///
|
|
||||||
/// [`Wayland`]: WindowElement::Wayland
|
|
||||||
#[must_use]
|
|
||||||
pub fn is_wayland(&self) -> bool {
|
|
||||||
matches!(self, Self::Wayland(..))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the window element is [`X11`].
|
|
||||||
///
|
|
||||||
/// [`X11`]: WindowElement::X11
|
|
||||||
#[must_use]
|
|
||||||
pub fn is_x11(&self) -> bool {
|
|
||||||
matches!(self, Self::X11(..))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the window element is [`X11OverrideRedirect`].
|
|
||||||
///
|
|
||||||
/// [`X11OverrideRedirect`]: WindowElement::X11OverrideRedirect
|
|
||||||
#[must_use]
|
|
||||||
pub fn is_x11_override_redirect(&self) -> bool {
|
pub fn is_x11_override_redirect(&self) -> bool {
|
||||||
matches!(self, Self::X11OverrideRedirect(..))
|
matches!(self.x11_surface(), Some(surface) if surface.is_override_redirect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpaceElement for WindowElement {
|
||||||
|
fn bbox(&self) -> Rectangle<i32, Logical> {
|
||||||
|
self.0.bbox()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_in_input_region(&self, point: &Point<f64, Logical>) -> bool {
|
||||||
|
self.0.is_in_input_region(point)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_activate(&self, activated: bool) {
|
||||||
|
self.0.set_activate(activated)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_enter(&self, output: &Output, overlap: Rectangle<i32, Logical>) {
|
||||||
|
self.0.output_enter(output, overlap)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_leave(&self, output: &Output) {
|
||||||
|
self.0.output_leave(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn geometry(&self) -> Rectangle<i32, Logical> {
|
||||||
|
self.0.geometry()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn z_index(&self) -> u8 {
|
||||||
|
self.0.z_index()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn refresh(&self) {
|
||||||
|
self.0.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsAlive for WindowElement {
|
||||||
|
fn alive(&self) -> bool {
|
||||||
|
self.0.alive()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PointerTarget<State> for WindowElement {
|
impl PointerTarget<State> for WindowElement {
|
||||||
fn frame(&self, seat: &Seat<State>, state: &mut State) {
|
fn frame(&self, seat: &Seat<State>, state: &mut State) {
|
||||||
match self {
|
match self.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => window
|
WindowSurface::Wayland(toplevel) => {
|
||||||
.wl_surface()
|
PointerTarget::frame(toplevel.wl_surface(), seat, state);
|
||||||
.expect("in wayland enum")
|
|
||||||
.frame(seat, state),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
surface.frame(seat, state)
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
WindowSurface::X11(surface) => PointerTarget::frame(surface, seat, state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enter(&self, seat: &Seat<State>, state: &mut State, event: &MotionEvent) {
|
fn enter(&self, seat: &Seat<State>, state: &mut State, event: &MotionEvent) {
|
||||||
// TODO: ssd
|
match self.underlying_surface() {
|
||||||
match self {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
WindowElement::Wayland(window) => PointerTarget::enter(
|
PointerTarget::enter(toplevel.wl_surface(), seat, state, event);
|
||||||
&window.wl_surface().expect("in wayland enum"),
|
|
||||||
seat,
|
|
||||||
state,
|
|
||||||
event,
|
|
||||||
),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
PointerTarget::enter(surface, seat, state, event)
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
WindowSurface::X11(surface) => PointerTarget::enter(surface, seat, state, event),
|
||||||
}
|
}
|
||||||
|
|
||||||
let window_id = Some(self.with_state(|state| state.id.0));
|
let window_id = Some(self.with_state(|state| state.id.0));
|
||||||
|
@ -375,18 +229,11 @@ impl PointerTarget<State> for WindowElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn motion(&self, seat: &Seat<State>, state: &mut State, event: &MotionEvent) {
|
fn motion(&self, seat: &Seat<State>, state: &mut State, event: &MotionEvent) {
|
||||||
// TODO: ssd
|
match self.underlying_surface() {
|
||||||
match self {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
WindowElement::Wayland(window) => PointerTarget::motion(
|
PointerTarget::motion(toplevel.wl_surface(), seat, state, event);
|
||||||
&window.wl_surface().expect("in wayland enum"),
|
|
||||||
seat,
|
|
||||||
state,
|
|
||||||
event,
|
|
||||||
),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
PointerTarget::motion(surface, seat, state, event)
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
WindowSurface::X11(surface) => PointerTarget::motion(surface, seat, state, event),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,20 +243,13 @@ impl PointerTarget<State> for WindowElement {
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
event: &smithay::input::pointer::RelativeMotionEvent,
|
event: &smithay::input::pointer::RelativeMotionEvent,
|
||||||
) {
|
) {
|
||||||
// TODO: ssd
|
match self.underlying_surface() {
|
||||||
match self {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
WindowElement::Wayland(window) => {
|
PointerTarget::relative_motion(toplevel.wl_surface(), seat, state, event);
|
||||||
PointerTarget::relative_motion(
|
|
||||||
&window.wl_surface().expect("in wayland enum"),
|
|
||||||
seat,
|
|
||||||
state,
|
|
||||||
event,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
PointerTarget::relative_motion(surface, seat, state, event);
|
PointerTarget::relative_motion(surface, seat, state, event);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,53 +259,29 @@ impl PointerTarget<State> for WindowElement {
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
event: &smithay::input::pointer::ButtonEvent,
|
event: &smithay::input::pointer::ButtonEvent,
|
||||||
) {
|
) {
|
||||||
// TODO: ssd
|
match self.underlying_surface() {
|
||||||
match self {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
WindowElement::Wayland(window) => PointerTarget::button(
|
PointerTarget::button(toplevel.wl_surface(), seat, state, event);
|
||||||
&window.wl_surface().expect("in wayland enum"),
|
|
||||||
seat,
|
|
||||||
state,
|
|
||||||
event,
|
|
||||||
),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
PointerTarget::button(surface, seat, state, event)
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
WindowSurface::X11(surface) => PointerTarget::button(surface, seat, state, event),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn axis(&self, seat: &Seat<State>, state: &mut State, frame: AxisFrame) {
|
fn axis(&self, seat: &Seat<State>, state: &mut State, frame: AxisFrame) {
|
||||||
// TODO: ssd
|
match self.underlying_surface() {
|
||||||
match self {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
WindowElement::Wayland(window) => PointerTarget::axis(
|
PointerTarget::axis(toplevel.wl_surface(), seat, state, frame);
|
||||||
&window.wl_surface().expect("in wayland enum"),
|
|
||||||
seat,
|
|
||||||
state,
|
|
||||||
frame,
|
|
||||||
),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
PointerTarget::axis(surface, seat, state, frame)
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
WindowSurface::X11(surface) => PointerTarget::axis(surface, seat, state, frame),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn leave(&self, seat: &Seat<State>, state: &mut State, serial: Serial, time: u32) {
|
fn leave(&self, seat: &Seat<State>, state: &mut State, serial: Serial, time: u32) {
|
||||||
// TODO: ssd
|
match self.underlying_surface() {
|
||||||
match self {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
WindowElement::Wayland(window) => {
|
PointerTarget::leave(toplevel.wl_surface(), seat, state, serial, time);
|
||||||
PointerTarget::leave(
|
|
||||||
&window.wl_surface().expect("in wayland enum"),
|
|
||||||
seat,
|
|
||||||
state,
|
|
||||||
serial,
|
|
||||||
time,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
WindowSurface::X11(surface) => PointerTarget::leave(surface, seat, state, serial, time),
|
||||||
PointerTarget::leave(surface, seat, state, serial, time)
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let window_id = Some(self.with_state(|state| state.id.0));
|
let window_id = Some(self.with_state(|state| state.id.0));
|
||||||
|
@ -557,35 +373,22 @@ impl KeyboardTarget<State> for WindowElement {
|
||||||
keys: Vec<KeysymHandle<'_>>,
|
keys: Vec<KeysymHandle<'_>>,
|
||||||
serial: Serial,
|
serial: Serial,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
KeyboardTarget::enter(
|
KeyboardTarget::enter(toplevel.wl_surface(), seat, state, keys, serial);
|
||||||
&window.wl_surface().expect("in wayland enum"),
|
|
||||||
seat,
|
|
||||||
state,
|
|
||||||
keys,
|
|
||||||
serial,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
KeyboardTarget::enter(surface, seat, state, keys, serial)
|
KeyboardTarget::enter(surface, seat, state, keys, serial);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn leave(&self, seat: &Seat<State>, state: &mut State, serial: Serial) {
|
fn leave(&self, seat: &Seat<State>, state: &mut State, serial: Serial) {
|
||||||
match self {
|
match self.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => KeyboardTarget::leave(
|
WindowSurface::Wayland(toplevel) => {
|
||||||
&window.wl_surface().expect("in wayland enum"),
|
KeyboardTarget::leave(toplevel.wl_surface(), seat, state, serial);
|
||||||
seat,
|
|
||||||
state,
|
|
||||||
serial,
|
|
||||||
),
|
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
|
||||||
KeyboardTarget::leave(surface, seat, state, serial)
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
WindowSurface::X11(surface) => KeyboardTarget::leave(surface, seat, state, serial),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,10 +401,10 @@ impl KeyboardTarget<State> for WindowElement {
|
||||||
serial: Serial,
|
serial: Serial,
|
||||||
time: u32,
|
time: u32,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
KeyboardTarget::key(
|
KeyboardTarget::key(
|
||||||
&window.wl_surface().expect("in wayland enum"),
|
toplevel.wl_surface(),
|
||||||
seat,
|
seat,
|
||||||
state,
|
state,
|
||||||
key,
|
key,
|
||||||
|
@ -610,10 +413,9 @@ impl KeyboardTarget<State> for WindowElement {
|
||||||
time,
|
time,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
KeyboardTarget::key(surface, seat, state, key, key_state, serial, time);
|
KeyboardTarget::key(surface, seat, state, key, key_state, serial, time);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,20 +426,13 @@ impl KeyboardTarget<State> for WindowElement {
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
serial: Serial,
|
serial: Serial,
|
||||||
) {
|
) {
|
||||||
match self {
|
match self.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
KeyboardTarget::modifiers(
|
KeyboardTarget::modifiers(toplevel.wl_surface(), seat, state, modifiers, serial);
|
||||||
&window.wl_surface().expect("in wayland enum"),
|
|
||||||
seat,
|
|
||||||
state,
|
|
||||||
modifiers,
|
|
||||||
serial,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) | WindowElement::X11OverrideRedirect(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
KeyboardTarget::modifiers(surface, seat, state, modifiers, serial);
|
KeyboardTarget::modifiers(surface, seat, state, modifiers, serial);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -663,12 +458,18 @@ impl State {
|
||||||
self.space
|
self.space
|
||||||
.elements()
|
.elements()
|
||||||
.find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false))
|
.find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false))
|
||||||
.cloned()
|
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.windows
|
self.windows
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface))
|
.find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface))
|
||||||
.cloned()
|
|
||||||
})
|
})
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_window_for_surface(&self, surface: &WlSurface) -> Option<WindowElement> {
|
||||||
|
self.new_windows
|
||||||
|
.iter()
|
||||||
|
.find(|&win| win.wl_surface().is_some_and(|surf| &surf == surface))
|
||||||
|
.cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
desktop::space::SpaceElement,
|
desktop::{space::SpaceElement, WindowSurface},
|
||||||
reexports::wayland_protocols::xdg::shell::server::xdg_toplevel,
|
reexports::wayland_protocols::xdg::shell::server::xdg_toplevel,
|
||||||
utils::{Logical, Point, Rectangle},
|
utils::{Logical, Point, Rectangle},
|
||||||
};
|
};
|
||||||
|
@ -81,30 +81,27 @@ impl WindowElement {
|
||||||
state.fullscreen_or_maximized = FullscreenOrMaximized::Fullscreen;
|
state.fullscreen_or_maximized = FullscreenOrMaximized::Fullscreen;
|
||||||
});
|
});
|
||||||
|
|
||||||
match self {
|
match self.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
window
|
toplevel.with_pending_state(|state| {
|
||||||
.toplevel()
|
state.states.unset(xdg_toplevel::State::Maximized);
|
||||||
.expect("in wayland enum")
|
state.states.set(xdg_toplevel::State::Fullscreen);
|
||||||
.with_pending_state(|state| {
|
state.states.set(xdg_toplevel::State::TiledTop);
|
||||||
state.states.unset(xdg_toplevel::State::Maximized);
|
state.states.set(xdg_toplevel::State::TiledLeft);
|
||||||
state.states.set(xdg_toplevel::State::Fullscreen);
|
state.states.set(xdg_toplevel::State::TiledBottom);
|
||||||
state.states.set(xdg_toplevel::State::TiledTop);
|
state.states.set(xdg_toplevel::State::TiledRight);
|
||||||
state.states.set(xdg_toplevel::State::TiledLeft);
|
});
|
||||||
state.states.set(xdg_toplevel::State::TiledBottom);
|
|
||||||
state.states.set(xdg_toplevel::State::TiledRight);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
surface
|
if !surface.is_override_redirect() {
|
||||||
.set_maximized(false)
|
surface
|
||||||
.expect("failed to set x11 win to maximized");
|
.set_maximized(false)
|
||||||
surface
|
.expect("failed to set x11 win to maximized");
|
||||||
.set_fullscreen(true)
|
surface
|
||||||
.expect("failed to set x11 win to not fullscreen");
|
.set_fullscreen(true)
|
||||||
|
.expect("failed to set x11 win to not fullscreen");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WindowElement::X11OverrideRedirect(_) => (),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FullscreenOrMaximized::Fullscreen => {
|
FullscreenOrMaximized::Fullscreen => {
|
||||||
|
@ -131,30 +128,27 @@ impl WindowElement {
|
||||||
state.fullscreen_or_maximized = FullscreenOrMaximized::Maximized;
|
state.fullscreen_or_maximized = FullscreenOrMaximized::Maximized;
|
||||||
});
|
});
|
||||||
|
|
||||||
match self {
|
match self.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
window
|
toplevel.with_pending_state(|state| {
|
||||||
.toplevel()
|
state.states.set(xdg_toplevel::State::Maximized);
|
||||||
.expect("in wayland enum")
|
state.states.unset(xdg_toplevel::State::Fullscreen);
|
||||||
.with_pending_state(|state| {
|
state.states.set(xdg_toplevel::State::TiledTop);
|
||||||
state.states.set(xdg_toplevel::State::Maximized);
|
state.states.set(xdg_toplevel::State::TiledLeft);
|
||||||
state.states.unset(xdg_toplevel::State::Fullscreen);
|
state.states.set(xdg_toplevel::State::TiledBottom);
|
||||||
state.states.set(xdg_toplevel::State::TiledTop);
|
state.states.set(xdg_toplevel::State::TiledRight);
|
||||||
state.states.set(xdg_toplevel::State::TiledLeft);
|
});
|
||||||
state.states.set(xdg_toplevel::State::TiledBottom);
|
|
||||||
state.states.set(xdg_toplevel::State::TiledRight);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
surface
|
if !surface.is_override_redirect() {
|
||||||
.set_maximized(true)
|
surface
|
||||||
.expect("failed to set x11 win to maximized");
|
.set_maximized(true)
|
||||||
surface
|
.expect("failed to set x11 win to maximized");
|
||||||
.set_fullscreen(false)
|
surface
|
||||||
.expect("failed to set x11 win to not fullscreen");
|
.set_fullscreen(false)
|
||||||
|
.expect("failed to set x11 win to not fullscreen");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WindowElement::X11OverrideRedirect(_) => (),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FullscreenOrMaximized::Maximized => {
|
FullscreenOrMaximized::Maximized => {
|
||||||
|
@ -176,60 +170,54 @@ impl WindowElement {
|
||||||
/// Unsets maximized and fullscreen states for both wayland and xwayland windows
|
/// Unsets maximized and fullscreen states for both wayland and xwayland windows
|
||||||
/// and unsets tiled states for wayland windows.
|
/// and unsets tiled states for wayland windows.
|
||||||
fn set_floating_states(&self) {
|
fn set_floating_states(&self) {
|
||||||
match self {
|
match self.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
window
|
toplevel.with_pending_state(|state| {
|
||||||
.toplevel()
|
state.states.unset(xdg_toplevel::State::Maximized);
|
||||||
.expect("in wayland enum")
|
state.states.unset(xdg_toplevel::State::Fullscreen);
|
||||||
.with_pending_state(|state| {
|
state.states.unset(xdg_toplevel::State::TiledTop);
|
||||||
state.states.unset(xdg_toplevel::State::Maximized);
|
state.states.unset(xdg_toplevel::State::TiledLeft);
|
||||||
state.states.unset(xdg_toplevel::State::Fullscreen);
|
state.states.unset(xdg_toplevel::State::TiledBottom);
|
||||||
state.states.unset(xdg_toplevel::State::TiledTop);
|
state.states.unset(xdg_toplevel::State::TiledRight);
|
||||||
state.states.unset(xdg_toplevel::State::TiledLeft);
|
});
|
||||||
state.states.unset(xdg_toplevel::State::TiledBottom);
|
|
||||||
state.states.unset(xdg_toplevel::State::TiledRight);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
surface
|
if !surface.is_override_redirect() {
|
||||||
.set_maximized(false)
|
surface
|
||||||
.expect("failed to set x11 win to maximized");
|
.set_maximized(false)
|
||||||
surface
|
.expect("failed to set x11 win to maximized");
|
||||||
.set_fullscreen(false)
|
surface
|
||||||
.expect("failed to set x11 win to not fullscreen");
|
.set_fullscreen(false)
|
||||||
|
.expect("failed to set x11 win to not fullscreen");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WindowElement::X11OverrideRedirect(_) => (),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsets maximized and fullscreen states for both wayland and xwayland windows
|
/// Unsets maximized and fullscreen states for both wayland and xwayland windows
|
||||||
/// and sets tiled states for wayland windows.
|
/// and sets tiled states for wayland windows.
|
||||||
fn set_tiled_states(&self) {
|
fn set_tiled_states(&self) {
|
||||||
match self {
|
match self.underlying_surface() {
|
||||||
WindowElement::Wayland(window) => {
|
WindowSurface::Wayland(toplevel) => {
|
||||||
window
|
toplevel.with_pending_state(|state| {
|
||||||
.toplevel()
|
state.states.unset(xdg_toplevel::State::Maximized);
|
||||||
.expect("in wayland enum")
|
state.states.unset(xdg_toplevel::State::Fullscreen);
|
||||||
.with_pending_state(|state| {
|
state.states.set(xdg_toplevel::State::TiledTop);
|
||||||
state.states.unset(xdg_toplevel::State::Maximized);
|
state.states.set(xdg_toplevel::State::TiledLeft);
|
||||||
state.states.unset(xdg_toplevel::State::Fullscreen);
|
state.states.set(xdg_toplevel::State::TiledBottom);
|
||||||
state.states.set(xdg_toplevel::State::TiledTop);
|
state.states.set(xdg_toplevel::State::TiledRight);
|
||||||
state.states.set(xdg_toplevel::State::TiledLeft);
|
});
|
||||||
state.states.set(xdg_toplevel::State::TiledBottom);
|
|
||||||
state.states.set(xdg_toplevel::State::TiledRight);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
WindowElement::X11(surface) => {
|
WindowSurface::X11(surface) => {
|
||||||
surface
|
if !surface.is_override_redirect() {
|
||||||
.set_maximized(false)
|
surface
|
||||||
.expect("failed to set x11 win to maximized");
|
.set_maximized(false)
|
||||||
surface
|
.expect("failed to set x11 win to maximized");
|
||||||
.set_fullscreen(false)
|
surface
|
||||||
.expect("failed to set x11 win to not fullscreen");
|
.set_fullscreen(false)
|
||||||
|
.expect("failed to set x11 win to not fullscreen");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
WindowElement::X11OverrideRedirect(_) => (),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue