mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-28 22:23:47 +01:00
Add WindowElement, xwayland stuff to state
This commit is contained in:
parent
087292b16f
commit
a146d5a4ad
4 changed files with 332 additions and 7 deletions
|
@ -1,5 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
pub mod xwayland;
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
|
|
99
src/handlers/xwayland.rs
Normal file
99
src/handlers/xwayland.rs
Normal 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!()
|
||||||
|
}
|
||||||
|
}
|
54
src/state.rs
54
src/state.rs
|
@ -8,6 +8,7 @@ use std::{
|
||||||
path::Path,
|
path::Path,
|
||||||
process::Stdio,
|
process::Stdio,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -15,6 +16,7 @@ use crate::{
|
||||||
msg::{Args, CallbackId, Msg, OutgoingMsg, Request, RequestId, RequestResponse},
|
msg::{Args, CallbackId, Msg, OutgoingMsg, Request, RequestId, RequestResponse},
|
||||||
PinnacleSocketSource,
|
PinnacleSocketSource,
|
||||||
},
|
},
|
||||||
|
cursor::Cursor,
|
||||||
focus::FocusState,
|
focus::FocusState,
|
||||||
grab::resize_grab::ResizeSurfaceState,
|
grab::resize_grab::ResizeSurfaceState,
|
||||||
tag::Tag,
|
tag::Tag,
|
||||||
|
@ -44,7 +46,7 @@ use smithay::{
|
||||||
Display,
|
Display,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
utils::{Clock, Logical, Monotonic, Point},
|
utils::{Clock, Logical, Monotonic, Point, Size},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{self, CompositorClientState, CompositorState},
|
compositor::{self, CompositorClientState, CompositorState},
|
||||||
data_device::DataDeviceState,
|
data_device::DataDeviceState,
|
||||||
|
@ -56,6 +58,7 @@ use smithay::{
|
||||||
socket::ListeningSocketSource,
|
socket::ListeningSocketSource,
|
||||||
viewporter::ViewporterState,
|
viewporter::ViewporterState,
|
||||||
},
|
},
|
||||||
|
xwayland::{X11Wm, XWayland, XWaylandEvent},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{backend::Backend, input::InputState};
|
use crate::{backend::Backend, input::InputState};
|
||||||
|
@ -97,6 +100,10 @@ pub struct State<B: Backend> {
|
||||||
// TODO: move into own struct
|
// TODO: move into own struct
|
||||||
// | basically just clean this mess up
|
// | basically just clean this mess up
|
||||||
pub output_callback_ids: Vec<CallbackId>,
|
pub output_callback_ids: Vec<CallbackId>,
|
||||||
|
|
||||||
|
pub xwayland: XWayland,
|
||||||
|
pub xwm: Option<X11Wm>,
|
||||||
|
pub xdisplay: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Backend> State<B> {
|
impl<B: Backend> State<B> {
|
||||||
|
@ -794,9 +801,48 @@ impl<B: Backend> State<B> {
|
||||||
Event::Msg(msg) => data.state.handle_msg(msg),
|
Event::Msg(msg) => data.state.handle_msg(msg),
|
||||||
Event::Closed => todo!(),
|
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 {
|
Ok(Self {
|
||||||
backend_data,
|
backend_data,
|
||||||
loop_signal,
|
loop_signal,
|
||||||
|
@ -830,6 +876,10 @@ impl<B: Backend> State<B> {
|
||||||
|
|
||||||
windows: vec![],
|
windows: vec![],
|
||||||
output_callback_ids: vec![],
|
output_callback_ids: vec![],
|
||||||
|
|
||||||
|
xwayland,
|
||||||
|
xwm: None,
|
||||||
|
xdisplay: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
184
src/window.rs
184
src/window.rs
|
@ -1,17 +1,31 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
use std::sync::atomic::AtomicU32;
|
use std::{cell::RefCell, sync::atomic::AtomicU32, time::Duration};
|
||||||
|
|
||||||
use smithay::{
|
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::{
|
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,
|
wayland_server::protocol::wl_surface::WlSurface,
|
||||||
},
|
},
|
||||||
|
utils::{user_data::UserDataMap, IsAlive, Logical, Point},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{Blocker, BlockerState},
|
compositor::{Blocker, BlockerState, SurfaceData},
|
||||||
|
dmabuf::DmabufFeedback,
|
||||||
seat::WaylandFocus,
|
seat::WaylandFocus,
|
||||||
},
|
},
|
||||||
|
xwayland::X11Surface,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -19,10 +33,170 @@ use crate::{
|
||||||
state::{State, WithState},
|
state::{State, WithState},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::window_state::Float;
|
use self::window_state::{Float, WindowState};
|
||||||
|
|
||||||
pub mod window_state;
|
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> {
|
impl<B: Backend> State<B> {
|
||||||
/// Returns the [Window] associated with a given [WlSurface].
|
/// Returns the [Window] associated with a given [WlSurface].
|
||||||
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<Window> {
|
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<Window> {
|
||||||
|
|
Loading…
Reference in a new issue