Add WindowElement, xwayland stuff to state

This commit is contained in:
Ottatop 2023-07-24 11:43:47 -05:00
parent 087292b16f
commit a146d5a4ad
4 changed files with 332 additions and 7 deletions

View file

@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pub mod xwayland;
use std::time::Duration;
use smithay::{

99
src/handlers/xwayland.rs Normal file
View file

@ -0,0 +1,99 @@
use smithay::xwayland::XwmHandler;
use crate::{backend::Backend, state::CalloopData};
impl<B: Backend> XwmHandler for CalloopData<B> {
fn xwm_state(&mut self, xwm: smithay::xwayland::xwm::XwmId) -> &mut smithay::xwayland::X11Wm {
todo!()
}
fn new_window(
&mut self,
xwm: smithay::xwayland::xwm::XwmId,
window: smithay::xwayland::X11Surface,
) {
todo!()
}
fn new_override_redirect_window(
&mut self,
xwm: smithay::xwayland::xwm::XwmId,
window: smithay::xwayland::X11Surface,
) {
todo!()
}
fn map_window_request(
&mut self,
xwm: smithay::xwayland::xwm::XwmId,
window: smithay::xwayland::X11Surface,
) {
todo!()
}
fn mapped_override_redirect_window(
&mut self,
xwm: smithay::xwayland::xwm::XwmId,
window: smithay::xwayland::X11Surface,
) {
todo!()
}
fn unmapped_window(
&mut self,
xwm: smithay::xwayland::xwm::XwmId,
window: smithay::xwayland::X11Surface,
) {
todo!()
}
fn destroyed_window(
&mut self,
xwm: smithay::xwayland::xwm::XwmId,
window: smithay::xwayland::X11Surface,
) {
todo!()
}
fn configure_request(
&mut self,
xwm: smithay::xwayland::xwm::XwmId,
window: smithay::xwayland::X11Surface,
x: Option<i32>,
y: Option<i32>,
w: Option<u32>,
h: Option<u32>,
reorder: Option<smithay::xwayland::xwm::Reorder>,
) {
todo!()
}
fn configure_notify(
&mut self,
xwm: smithay::xwayland::xwm::XwmId,
window: smithay::xwayland::X11Surface,
geometry: smithay::utils::Rectangle<i32, smithay::utils::Logical>,
above: Option<smithay::reexports::x11rb::protocol::xproto::Window>,
) {
todo!()
}
fn resize_request(
&mut self,
xwm: smithay::xwayland::xwm::XwmId,
window: smithay::xwayland::X11Surface,
button: u32,
resize_edge: smithay::xwayland::xwm::ResizeEdge,
) {
todo!()
}
fn move_request(
&mut self,
xwm: smithay::xwayland::xwm::XwmId,
window: smithay::xwayland::X11Surface,
button: u32,
) {
todo!()
}
}

View file

@ -8,6 +8,7 @@ use std::{
path::Path,
process::Stdio,
sync::{Arc, Mutex},
time::Duration,
};
use crate::{
@ -15,6 +16,7 @@ use crate::{
msg::{Args, CallbackId, Msg, OutgoingMsg, Request, RequestId, RequestResponse},
PinnacleSocketSource,
},
cursor::Cursor,
focus::FocusState,
grab::resize_grab::ResizeSurfaceState,
tag::Tag,
@ -44,7 +46,7 @@ use smithay::{
Display,
},
},
utils::{Clock, Logical, Monotonic, Point},
utils::{Clock, Logical, Monotonic, Point, Size},
wayland::{
compositor::{self, CompositorClientState, CompositorState},
data_device::DataDeviceState,
@ -56,6 +58,7 @@ use smithay::{
socket::ListeningSocketSource,
viewporter::ViewporterState,
},
xwayland::{X11Wm, XWayland, XWaylandEvent},
};
use crate::{backend::Backend, input::InputState};
@ -97,6 +100,10 @@ pub struct State<B: Backend> {
// TODO: move into own struct
// | basically just clean this mess up
pub output_callback_ids: Vec<CallbackId>,
pub xwayland: XWayland,
pub xwm: Option<X11Wm>,
pub xdisplay: Option<u32>,
}
impl<B: Backend> State<B> {
@ -794,9 +801,48 @@ impl<B: Backend> State<B> {
Event::Msg(msg) => data.state.handle_msg(msg),
Event::Closed => todo!(),
})
.unwrap(); // TODO: unwrap
.expect("failed to insert rx_channel into loop");
});
let xwayland = {
let (xwayland, channel) = XWayland::new(&display_handle);
let clone = display_handle.clone();
let res =
loop_handle.insert_source(channel, move |event, _metadata, data| match event {
XWaylandEvent::Ready {
connection,
client,
client_fd: _,
display,
} => {
let mut wm = X11Wm::start_wm(
data.state.loop_handle.clone(),
clone.clone(),
connection,
client,
)
.expect("failed to attach x11wm");
let cursor = Cursor::load();
let image = cursor.get_image(1, Duration::ZERO);
wm.set_cursor(
&image.pixels_rgba,
Size::from((image.width as u16, image.height as u16)),
Point::from((image.xhot as u16, image.yhot as u16)),
)
.expect("failed to set xwayland default cursor");
data.state.xwm = Some(wm);
data.state.xdisplay = Some(display);
}
XWaylandEvent::Exited => {
data.state.xwm.take();
}
});
if let Err(err) = res {
tracing::error!("Failed to insert XWayland source into loop: {err}");
}
xwayland
};
Ok(Self {
backend_data,
loop_signal,
@ -830,6 +876,10 @@ impl<B: Backend> State<B> {
windows: vec![],
output_callback_ids: vec![],
xwayland,
xwm: None,
xdisplay: None,
})
}
}

View file

@ -1,17 +1,31 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use std::sync::atomic::AtomicU32;
use std::{cell::RefCell, sync::atomic::AtomicU32, time::Duration};
use smithay::{
desktop::Window,
desktop::{
utils::{
send_dmabuf_feedback_surface_tree, send_frames_surface_tree,
take_presentation_feedback_surface_tree, with_surfaces_surface_tree,
OutputPresentationFeedback,
},
Window, WindowSurfaceType,
},
output::Output,
reexports::{
wayland_protocols::xdg::shell::server::xdg_toplevel,
wayland_protocols::{
wp::presentation_time::server::wp_presentation_feedback,
xdg::shell::server::xdg_toplevel,
},
wayland_server::protocol::wl_surface::WlSurface,
},
utils::{user_data::UserDataMap, IsAlive, Logical, Point},
wayland::{
compositor::{Blocker, BlockerState},
compositor::{Blocker, BlockerState, SurfaceData},
dmabuf::DmabufFeedback,
seat::WaylandFocus,
},
xwayland::X11Surface,
};
use crate::{
@ -19,10 +33,170 @@ use crate::{
state::{State, WithState},
};
use self::window_state::Float;
use self::window_state::{Float, WindowState};
pub mod window_state;
#[derive(Debug, Clone, PartialEq)]
pub enum WindowElement {
Wayland(Window),
X11(X11Surface),
}
impl WindowElement {
pub fn surface_under(
&self,
location: Point<i32, Logical>,
window_type: WindowSurfaceType,
) -> Option<(WlSurface, Point<i32, Logical>)> {
todo!()
}
pub fn with_surfaces<F>(&self, processor: F)
where
F: FnMut(&WlSurface, &SurfaceData) + Copy,
{
match self {
WindowElement::Wayland(window) => window.with_surfaces(processor),
WindowElement::X11(surface) => {
if let Some(surface) = surface.wl_surface() {
with_surfaces_surface_tree(&surface, processor);
}
}
}
}
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) => {
if let Some(surface) = surface.wl_surface() {
send_frames_surface_tree(
&surface,
output,
time,
throttle,
primary_scan_out_output,
);
}
}
}
}
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) => {
if let Some(surface) = surface.wl_surface() {
send_dmabuf_feedback_surface_tree(
&surface,
output,
primary_scan_out_output,
select_dmabuf_feedback,
);
}
}
}
}
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) => {
if let Some(surface) = surface.wl_surface() {
take_presentation_feedback_surface_tree(
&surface,
output_feedback,
primary_scan_out_output,
presentation_feedback_flags,
);
}
}
}
}
pub fn wl_surface(&self) -> Option<WlSurface> {
match self {
WindowElement::Wayland(window) => window.wl_surface(),
WindowElement::X11(surface) => surface.wl_surface(),
}
}
pub fn user_data(&self) -> &UserDataMap {
match self {
WindowElement::Wayland(window) => window.user_data(),
WindowElement::X11(surface) => surface.user_data(),
}
}
}
impl IsAlive for WindowElement {
fn alive(&self) -> bool {
match self {
WindowElement::Wayland(window) => window.alive(),
WindowElement::X11(surface) => surface.alive(),
}
}
}
impl WithState for WindowElement {
type State = WindowState;
fn with_state<F, T>(&self, mut func: F) -> T
where
F: FnMut(&mut Self::State) -> T,
{
self.user_data()
.insert_if_missing(RefCell::<Self::State>::default);
let state = self
.user_data()
.get::<RefCell<Self::State>>()
.expect("RefCell not in data map");
func(&mut state.borrow_mut())
}
}
impl<B: Backend> State<B> {
/// Returns the [Window] associated with a given [WlSurface].
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<Window> {