server: give uninitialized and initialized xstate with unique types
This commit is contained in:
parent
56d5cce2d0
commit
4280639df8
4 changed files with 180 additions and 137 deletions
46
src/lib.rs
46
src/lib.rs
|
|
@ -1,7 +1,7 @@
|
||||||
mod server;
|
mod server;
|
||||||
pub mod xstate;
|
pub mod xstate;
|
||||||
|
|
||||||
use crate::server::{PendingSurfaceState, ServerState};
|
use crate::server::{EarlyConnection, PendingSurfaceState, ServerState};
|
||||||
use crate::xstate::{RealConnection, XState};
|
use crate::xstate::{RealConnection, XState};
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use rustix::event::{poll, PollFd, PollFlags};
|
use rustix::event::{poll, PollFd, PollFlags};
|
||||||
|
|
@ -16,7 +16,6 @@ use xcb::x;
|
||||||
pub trait XConnection: Sized + 'static {
|
pub trait XConnection: Sized + 'static {
|
||||||
type X11Selection: X11Selection;
|
type X11Selection: X11Selection;
|
||||||
|
|
||||||
fn root_window(&self) -> x::Window;
|
|
||||||
fn set_window_dims(&mut self, window: x::Window, dims: PendingSurfaceState);
|
fn set_window_dims(&mut self, window: x::Window, dims: PendingSurfaceState);
|
||||||
fn set_fullscreen(&mut self, window: x::Window, fullscreen: bool);
|
fn set_fullscreen(&mut self, window: x::Window, fullscreen: bool);
|
||||||
fn focus_window(&mut self, window: x::Window, output_name: Option<String>);
|
fn focus_window(&mut self, window: x::Window, output_name: Option<String>);
|
||||||
|
|
@ -30,6 +29,7 @@ pub trait X11Selection {
|
||||||
fn write_to(&self, mime: &str, pipe: WritePipe);
|
fn write_to(&self, mime: &str, pipe: WritePipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EarlyServerState = ServerState<EarlyConnection<<RealConnection as XConnection>::X11Selection>>;
|
||||||
type RealServerState = ServerState<RealConnection>;
|
type RealServerState = ServerState<RealConnection>;
|
||||||
|
|
||||||
pub trait RunData {
|
pub trait RunData {
|
||||||
|
|
@ -58,8 +58,6 @@ pub fn main(mut data: impl RunData) -> Option<()> {
|
||||||
let dh = display.handle();
|
let dh = display.handle();
|
||||||
data.created_server();
|
data.created_server();
|
||||||
|
|
||||||
let mut server_state = RealServerState::new(dh, data.server());
|
|
||||||
|
|
||||||
let (xsock_wl, xsock_xwl) = UnixStream::pair().unwrap();
|
let (xsock_wl, xsock_xwl) = UnixStream::pair().unwrap();
|
||||||
// Prevent creation of new Xwayland command from closing fd
|
// Prevent creation of new Xwayland command from closing fd
|
||||||
rustix::io::fcntl_setfd(&xsock_xwl, rustix::io::FdFlags::empty()).unwrap();
|
rustix::io::fcntl_setfd(&xsock_xwl, rustix::io::FdFlags::empty()).unwrap();
|
||||||
|
|
@ -136,11 +134,10 @@ pub fn main(mut data: impl RunData) -> Option<()> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut server_state = EarlyServerState::new(dh, data.server());
|
||||||
server_state.connect(connection);
|
server_state.connect(connection);
|
||||||
server_state.run();
|
server_state.run();
|
||||||
|
|
||||||
let mut xstate: Option<XState> = None;
|
|
||||||
|
|
||||||
// Remove the lifetimes on our fds to avoid borrowing issues, since we know they will exist for
|
// Remove the lifetimes on our fds to avoid borrowing issues, since we know they will exist for
|
||||||
// the rest of our program anyway
|
// the rest of our program anyway
|
||||||
let server_fd = unsafe { BorrowedFd::borrow_raw(server_state.clientside_fd().as_raw_fd()) };
|
let server_fd = unsafe { BorrowedFd::borrow_raw(server_state.clientside_fd().as_raw_fd()) };
|
||||||
|
|
@ -154,38 +151,44 @@ pub fn main(mut data: impl RunData) -> Option<()> {
|
||||||
PollFd::from_borrowed_fd(server_fd, PollFlags::IN),
|
PollFd::from_borrowed_fd(server_fd, PollFlags::IN),
|
||||||
PollFd::new(&xsock_wl, PollFlags::IN),
|
PollFd::new(&xsock_wl, PollFlags::IN),
|
||||||
PollFd::from_borrowed_fd(display_fd, PollFlags::IN),
|
PollFd::from_borrowed_fd(display_fd, PollFlags::IN),
|
||||||
PollFd::new(&ready_rx, PollFlags::IN),
|
|
||||||
PollFd::new(&quit_rx, PollFlags::IN),
|
PollFd::new(&quit_rx, PollFlags::IN),
|
||||||
|
PollFd::new(&ready_rx, PollFlags::IN),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut ready = false;
|
|
||||||
loop {
|
loop {
|
||||||
match poll(&mut fds, -1) {
|
match poll(&mut fds, -1) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
if !fds[3].revents().is_empty() {
|
if !fds[3].revents().is_empty() {
|
||||||
ready = true;
|
|
||||||
}
|
|
||||||
if !fds[4].revents().is_empty() {
|
|
||||||
let status = xwayland_exit_code(&mut quit_rx);
|
let status = xwayland_exit_code(&mut quit_rx);
|
||||||
if *status != ExitStatus::default() {
|
if *status != ExitStatus::default() {
|
||||||
error!("Xwayland exited early with {status}");
|
error!("Xwayland exited early with {status}");
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
if !fds[4].revents().is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(other) => panic!("Poll failed: {other:?}"),
|
Err(other) => panic!("Poll failed: {other:?}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if xstate.is_none() && ready {
|
display.dispatch_clients(server_state.inner_mut()).unwrap();
|
||||||
|
server_state.run();
|
||||||
|
display.flush_clients().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut xstate: Option<XState> = None;
|
||||||
let xstate = xstate.insert(XState::new(xsock_wl.as_fd()));
|
let xstate = xstate.insert(XState::new(xsock_wl.as_fd()));
|
||||||
let mut reader = BufReader::new(&ready_rx);
|
let mut reader = BufReader::new(&ready_rx);
|
||||||
|
{
|
||||||
let mut display = String::new();
|
let mut display = String::new();
|
||||||
reader.read_line(&mut display).unwrap();
|
reader.read_line(&mut display).unwrap();
|
||||||
display.pop();
|
display.pop();
|
||||||
display.insert(0, ':');
|
display.insert(0, ':');
|
||||||
info!("Connected to Xwayland on {display}");
|
info!("Connected to Xwayland on {display}");
|
||||||
data.xwayland_ready(display, xwl_pid);
|
data.xwayland_ready(display, xwl_pid);
|
||||||
xstate.server_state_setup(&mut server_state);
|
}
|
||||||
|
let mut server_state = xstate.server_state_setup(server_state);
|
||||||
|
|
||||||
#[cfg(feature = "systemd")]
|
#[cfg(feature = "systemd")]
|
||||||
{
|
{
|
||||||
|
|
@ -197,17 +200,14 @@ pub fn main(mut data: impl RunData) -> Option<()> {
|
||||||
|
|
||||||
#[cfg(not(feature = "systemd"))]
|
#[cfg(not(feature = "systemd"))]
|
||||||
info!("Systemd support disabled.");
|
info!("Systemd support disabled.");
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(xstate) = &mut xstate {
|
loop {
|
||||||
xstate.handle_events(&mut server_state);
|
xstate.handle_events(&mut server_state);
|
||||||
}
|
|
||||||
|
|
||||||
display.dispatch_clients(server_state.inner_mut()).unwrap();
|
display.dispatch_clients(server_state.inner_mut()).unwrap();
|
||||||
server_state.run();
|
server_state.run();
|
||||||
display.flush_clients().unwrap();
|
display.flush_clients().unwrap();
|
||||||
|
|
||||||
if let Some(xstate) = &mut xstate {
|
|
||||||
if let Some(sel) = server_state.new_selection() {
|
if let Some(sel) = server_state.new_selection() {
|
||||||
xstate.set_clipboard(sel);
|
xstate.set_clipboard(sel);
|
||||||
}
|
}
|
||||||
|
|
@ -215,6 +215,18 @@ pub fn main(mut data: impl RunData) -> Option<()> {
|
||||||
if let Some(scale) = server_state.new_global_scale() {
|
if let Some(scale) = server_state.new_global_scale() {
|
||||||
xstate.update_global_scale(scale);
|
xstate.update_global_scale(scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match poll(&mut fds, -1) {
|
||||||
|
Ok(_) => {
|
||||||
|
if !fds[3].revents().is_empty() {
|
||||||
|
let status = xwayland_exit_code(&mut quit_rx);
|
||||||
|
if *status != ExitStatus::default() {
|
||||||
|
error!("Xwayland exited early with {status}");
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(other) => panic!("Poll failed: {other:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -393,6 +393,33 @@ struct GlobalOutputOffset {
|
||||||
y: GlobalOutputOffsetDimension,
|
y: GlobalOutputOffsetDimension,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The state of the X11 connection before XState has been fully initialized.
|
||||||
|
/// It implements XConnection minimally, gracefully doing nothing but logging the called functions.
|
||||||
|
pub struct EarlyConnection<S: X11Selection + 'static> {
|
||||||
|
_p: std::marker::PhantomData<S>,
|
||||||
|
}
|
||||||
|
impl<S: X11Selection> XConnection for EarlyConnection<S> {
|
||||||
|
type X11Selection = S;
|
||||||
|
fn focus_window(&mut self, _: x::Window, _: Option<String>) {
|
||||||
|
debug!("could not focus window without XWayland initialized");
|
||||||
|
}
|
||||||
|
fn close_window(&mut self, _: x::Window) {
|
||||||
|
debug!("could not close window without XWayland initialized");
|
||||||
|
}
|
||||||
|
fn unmap_window(&mut self, _: x::Window) {
|
||||||
|
debug!("could not unmap window without XWayland initialized");
|
||||||
|
}
|
||||||
|
fn raise_to_top(&mut self, _: x::Window) {
|
||||||
|
debug!("could not raise window to top without XWayland initialized");
|
||||||
|
}
|
||||||
|
fn set_fullscreen(&mut self, _: x::Window, _: bool) {
|
||||||
|
debug!("could not toggle fullscreen without XWayland initialized");
|
||||||
|
}
|
||||||
|
fn set_window_dims(&mut self, _: x::Window, _: crate::server::PendingSurfaceState) {
|
||||||
|
debug!("could not set window dimensions without XWayland initialized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ServerState<C: XConnection> {
|
pub struct ServerState<C: XConnection> {
|
||||||
inner: InnerServerState<C::X11Selection>,
|
inner: InnerServerState<C::X11Selection>,
|
||||||
pub connection: Option<C>,
|
pub connection: Option<C>,
|
||||||
|
|
@ -425,7 +452,7 @@ pub struct InnerServerState<S: X11Selection> {
|
||||||
new_scale: Option<f64>,
|
new_scale: Option<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: XConnection> ServerState<C> {
|
impl<S: X11Selection> ServerState<EarlyConnection<S>> {
|
||||||
pub fn new(dh: DisplayHandle, server_connection: Option<UnixStream>) -> Self {
|
pub fn new(dh: DisplayHandle, server_connection: Option<UnixStream>) -> Self {
|
||||||
let connection = if let Some(stream) = server_connection {
|
let connection = if let Some(stream) = server_connection {
|
||||||
Connection::from_socket(stream).unwrap()
|
Connection::from_socket(stream).unwrap()
|
||||||
|
|
@ -460,7 +487,7 @@ impl<C: XConnection> ServerState<C> {
|
||||||
let clipboard_data = manager.map(|manager| ClipboardData {
|
let clipboard_data = manager.map(|manager| ClipboardData {
|
||||||
manager,
|
manager,
|
||||||
device: None,
|
device: None,
|
||||||
source: None::<CopyPasteData<C::X11Selection>>,
|
source: None::<CopyPasteData<S>>,
|
||||||
});
|
});
|
||||||
|
|
||||||
let activation_state = ActivationState::bind(&global_list, &qh)
|
let activation_state = ActivationState::bind(&global_list, &qh)
|
||||||
|
|
@ -476,10 +503,10 @@ impl<C: XConnection> ServerState<C> {
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
dh.create_global::<InnerServerState<C::X11Selection>, XwaylandShellV1, _>(1, ());
|
dh.create_global::<InnerServerState<S>, XwaylandShellV1, _>(1, ());
|
||||||
global_list
|
global_list
|
||||||
.contents()
|
.contents()
|
||||||
.with_list(|globals| handle_globals::<C::X11Selection>(&dh, globals));
|
.with_list(|globals| handle_globals::<S>(&dh, globals));
|
||||||
|
|
||||||
let inner = InnerServerState {
|
let inner = InnerServerState {
|
||||||
windows: HashMap::new(),
|
windows: HashMap::new(),
|
||||||
|
|
@ -516,7 +543,19 @@ impl<C: XConnection> ServerState<C> {
|
||||||
};
|
};
|
||||||
Self {
|
Self {
|
||||||
inner,
|
inner,
|
||||||
connection: None,
|
connection: Some(EarlyConnection {
|
||||||
|
_p: std::marker::PhantomData,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn upgrade_connection<C>(self, connection: C) -> ServerState<C>
|
||||||
|
where
|
||||||
|
C: XConnection<X11Selection = S>,
|
||||||
|
{
|
||||||
|
ServerState {
|
||||||
|
inner: self.inner,
|
||||||
|
connection: Some(connection),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use super::{InnerServerState, ServerState, WindowDims};
|
use super::{EarlyConnection, InnerServerState, ServerState, WindowDims};
|
||||||
use crate::xstate::{SetState, WinSize, WmName};
|
use crate::xstate::{SetState, WinSize, WmName};
|
||||||
|
use crate::XConnection;
|
||||||
use rustix::event::{poll, PollFd, PollFlags};
|
use rustix::event::{poll, PollFd, PollFlags};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
@ -152,8 +153,8 @@ struct WindowData {
|
||||||
fullscreen: bool,
|
fullscreen: bool,
|
||||||
dims: WindowDims,
|
dims: WindowDims,
|
||||||
}
|
}
|
||||||
|
#[derive(Default)]
|
||||||
struct FakeXConnection {
|
struct FakeXConnection {
|
||||||
root: Window,
|
|
||||||
focused_window: Option<Window>,
|
focused_window: Option<Window>,
|
||||||
windows: HashMap<Window, WindowData>,
|
windows: HashMap<Window, WindowData>,
|
||||||
}
|
}
|
||||||
|
|
@ -174,16 +175,6 @@ impl FakeXConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FakeXConnection {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
root: unsafe { Window::new(9001) },
|
|
||||||
focused_window: None,
|
|
||||||
windows: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type FakeX11Selection = Vec<testwl::PasteData>;
|
type FakeX11Selection = Vec<testwl::PasteData>;
|
||||||
impl crate::X11Selection for Vec<testwl::PasteData> {
|
impl crate::X11Selection for Vec<testwl::PasteData> {
|
||||||
fn mime_types(&self) -> Vec<&str> {
|
fn mime_types(&self) -> Vec<&str> {
|
||||||
|
|
@ -206,10 +197,6 @@ impl crate::X11Selection for Vec<testwl::PasteData> {
|
||||||
|
|
||||||
impl super::XConnection for FakeXConnection {
|
impl super::XConnection for FakeXConnection {
|
||||||
type X11Selection = FakeX11Selection;
|
type X11Selection = FakeX11Selection;
|
||||||
fn root_window(&self) -> Window {
|
|
||||||
self.root
|
|
||||||
}
|
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn close_window(&mut self, window: Window) {
|
fn close_window(&mut self, window: Window) {
|
||||||
log::debug!("closing window {window:?}");
|
log::debug!("closing window {window:?}");
|
||||||
|
|
@ -252,15 +239,16 @@ impl super::XConnection for FakeXConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type FakeServerState = ServerState<FakeXConnection>;
|
type EarlyServerState = ServerState<EarlyConnection<FakeX11Selection>>;
|
||||||
|
type EarlyTestFixture = TestFixture<EarlyConnection<FakeX11Selection>>;
|
||||||
|
|
||||||
struct TestFixture {
|
struct TestFixture<C: XConnection> {
|
||||||
testwl: testwl::Server,
|
testwl: testwl::Server,
|
||||||
satellite: FakeServerState,
|
satellite: ServerState<C>,
|
||||||
/// Our connection to satellite - i.e., where Xwayland sends requests to
|
/// Our connection to satellite - i.e., where Xwayland sends requests to
|
||||||
xwls_connection: Arc<Connection>,
|
xwls_connection: Arc<Connection>,
|
||||||
/// Satellite's display - must dispatch this for our server state to advance
|
/// Satellite's display - must dispatch this for our server state to advance
|
||||||
xwls_display: Display<InnerServerState<FakeX11Selection>>,
|
xwls_display: Display<InnerServerState<C::X11Selection>>,
|
||||||
surface_serial: u64,
|
surface_serial: u64,
|
||||||
registry: TestObject<WlRegistry>,
|
registry: TestObject<WlRegistry>,
|
||||||
}
|
}
|
||||||
|
|
@ -336,38 +324,24 @@ impl PreConnectFn for () {}
|
||||||
|
|
||||||
struct SetupOptions<F> {
|
struct SetupOptions<F> {
|
||||||
pre_connect: Option<F>,
|
pre_connect: Option<F>,
|
||||||
connect_x: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SetupOptions<()> {
|
|
||||||
fn dont_connect_x() -> Self {
|
|
||||||
Self {
|
|
||||||
pre_connect: None,
|
|
||||||
connect_x: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: PreConnectFn> SetupOptions<F> {
|
impl<F: PreConnectFn> SetupOptions<F> {
|
||||||
fn pre_connect(pre_connect: F) -> Self {
|
fn pre_connect(pre_connect: F) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pre_connect: Some(pre_connect),
|
pre_connect: Some(pre_connect),
|
||||||
connect_x: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SetupOptions<()> {
|
impl Default for SetupOptions<()> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self { pre_connect: None }
|
||||||
pre_connect: None,
|
|
||||||
connect_x: true,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestFixture {
|
impl EarlyTestFixture {
|
||||||
fn new_with_options<F: PreConnectFn>(options: SetupOptions<F>) -> Self {
|
fn new_early_with_options<F: PreConnectFn>(options: SetupOptions<F>) -> Self {
|
||||||
INIT.call_once(|| {
|
INIT.call_once(|| {
|
||||||
env_logger::builder()
|
env_logger::builder()
|
||||||
.is_test(true)
|
.is_test(true)
|
||||||
|
|
@ -391,23 +365,19 @@ impl TestFixture {
|
||||||
testwl.dispatch();
|
testwl.dispatch();
|
||||||
testwl
|
testwl
|
||||||
});
|
});
|
||||||
let mut satellite = FakeServerState::new(display.handle(), Some(client_s));
|
|
||||||
let testwl = thread.join().unwrap();
|
|
||||||
|
|
||||||
let (fake_client, xwls_server) = UnixStream::pair().unwrap();
|
let (fake_client, xwls_server) = UnixStream::pair().unwrap();
|
||||||
|
let mut satellite = EarlyServerState::new(display.handle(), Some(client_s));
|
||||||
|
let testwl = thread.join().unwrap();
|
||||||
satellite.connect(xwls_server);
|
satellite.connect(xwls_server);
|
||||||
|
|
||||||
if options.connect_x {
|
|
||||||
satellite.set_x_connection(FakeXConnection::default());
|
|
||||||
}
|
|
||||||
|
|
||||||
let xwls_connection = Connection::from_socket(fake_client).unwrap();
|
let xwls_connection = Connection::from_socket(fake_client).unwrap();
|
||||||
let registry = TestObject::<WlRegistry>::from_request(
|
let registry = TestObject::<WlRegistry>::from_request(
|
||||||
&xwls_connection.display(),
|
&xwls_connection.display(),
|
||||||
Req::<WlDisplay>::GetRegistry {},
|
Req::<WlDisplay>::GetRegistry {},
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut f = TestFixture {
|
let mut f = EarlyTestFixture {
|
||||||
testwl,
|
testwl,
|
||||||
satellite,
|
satellite,
|
||||||
xwls_connection: xwls_connection.into(),
|
xwls_connection: xwls_connection.into(),
|
||||||
|
|
@ -419,24 +389,19 @@ impl TestFixture {
|
||||||
f
|
f
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new() -> Self {
|
fn upgrade_connection(self, connection: FakeXConnection) -> TestFixture<FakeXConnection> {
|
||||||
Self::new_with_options(SetupOptions::default())
|
TestFixture {
|
||||||
|
testwl: self.testwl,
|
||||||
|
satellite: self.satellite.upgrade_connection(connection),
|
||||||
|
xwls_connection: self.xwls_connection,
|
||||||
|
xwls_display: self.xwls_display,
|
||||||
|
surface_serial: self.surface_serial,
|
||||||
|
registry: self.registry,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_pre_connect(pre_connect: impl FnOnce(&mut testwl::Server)) -> Self {
|
|
||||||
Self::new_with_options(SetupOptions::pre_connect(pre_connect))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_with_compositor() -> (Self, Compositor) {
|
|
||||||
let mut f = Self::new();
|
|
||||||
let compositor = f.compositor();
|
|
||||||
(f, compositor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn connection(&self) -> &FakeXConnection {
|
|
||||||
self.satellite.connection.as_ref().unwrap()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: XConnection> TestFixture<C> {
|
||||||
fn compositor(&mut self) -> Compositor {
|
fn compositor(&mut self) -> Compositor {
|
||||||
let mut ret = CompositorOptional::default();
|
let mut ret = CompositorOptional::default();
|
||||||
let events = std::mem::take(&mut *self.registry.data.events.lock().unwrap());
|
let events = std::mem::take(&mut *self.registry.data.events.lock().unwrap());
|
||||||
|
|
@ -495,18 +460,6 @@ impl TestFixture {
|
||||||
ret.into()
|
ret.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_data<P>(&self, obj: &P) -> Arc<TestObjectData<P>>
|
|
||||||
where
|
|
||||||
P: Proxy + Send + Sync + 'static,
|
|
||||||
P::Event: Send + Sync + std::fmt::Debug,
|
|
||||||
{
|
|
||||||
self.xwls_connection
|
|
||||||
.get_object_data(obj.id())
|
|
||||||
.unwrap()
|
|
||||||
.downcast_arc::<TestObjectData<P>>()
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Cascade our requests/events through satellite and testwl
|
/// Cascade our requests/events through satellite and testwl
|
||||||
fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
// Flush our requests to satellite
|
// Flush our requests to satellite
|
||||||
|
|
@ -573,6 +526,43 @@ impl TestFixture {
|
||||||
self.run();
|
self.run();
|
||||||
(output, self.testwl.last_created_output())
|
(output, self.testwl.last_created_output())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestFixture<FakeXConnection> {
|
||||||
|
fn new_with_options<F: PreConnectFn>(options: SetupOptions<F>) -> Self {
|
||||||
|
EarlyTestFixture::new_early_with_options(options)
|
||||||
|
.upgrade_connection(FakeXConnection::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new() -> Self {
|
||||||
|
Self::new_with_options(SetupOptions::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_pre_connect(pre_connect: impl FnOnce(&mut testwl::Server)) -> Self {
|
||||||
|
Self::new_with_options(SetupOptions::pre_connect(pre_connect))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_with_compositor() -> (Self, Compositor) {
|
||||||
|
let mut f = Self::new();
|
||||||
|
let compositor = f.compositor();
|
||||||
|
(f, compositor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connection(&self) -> &FakeXConnection {
|
||||||
|
self.satellite.connection.as_ref().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn object_data<P>(&self, obj: &P) -> Arc<TestObjectData<P>>
|
||||||
|
where
|
||||||
|
P: Proxy + Send + Sync + 'static,
|
||||||
|
P::Event: Send + Sync + std::fmt::Debug,
|
||||||
|
{
|
||||||
|
self.xwls_connection
|
||||||
|
.get_object_data(obj.id())
|
||||||
|
.unwrap()
|
||||||
|
.downcast_arc::<TestObjectData<P>>()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
fn enable_xdg_output(&mut self) -> TestObject<ZxdgOutputManagerV1> {
|
fn enable_xdg_output(&mut self) -> TestObject<ZxdgOutputManagerV1> {
|
||||||
self.testwl.enable_xdg_output_manager();
|
self.testwl.enable_xdg_output_manager();
|
||||||
|
|
@ -1561,7 +1551,7 @@ fn output_offset_change() {
|
||||||
f.testwl.move_surface_to_output(id, &output);
|
f.testwl.move_surface_to_output(id, &output);
|
||||||
f.run();
|
f.run();
|
||||||
|
|
||||||
let test_position = |f: &TestFixture, x, y| {
|
let test_position = |f: &TestFixture<_>, x, y| {
|
||||||
let data = &f.connection().windows[&window];
|
let data = &f.connection().windows[&window];
|
||||||
assert_eq!(data.dims.x, x);
|
assert_eq!(data.dims.x, x);
|
||||||
assert_eq!(data.dims.y, y);
|
assert_eq!(data.dims.y, y);
|
||||||
|
|
@ -2320,7 +2310,7 @@ fn touch_fractional_scale() {
|
||||||
let server_surface = data.surface.clone();
|
let server_surface = data.surface.clone();
|
||||||
let fractional = data.fractional.as_ref().cloned().unwrap();
|
let fractional = data.fractional.as_ref().cloned().unwrap();
|
||||||
|
|
||||||
let do_touch = |f: &mut TestFixture, x, y| {
|
let do_touch = |f: &mut TestFixture<_>, x, y| {
|
||||||
f.testwl.touch().down(0, 0, &server_surface, 0, x, y);
|
f.testwl.touch().down(0, 0, &server_surface, 0, x, y);
|
||||||
f.testwl.dispatch();
|
f.testwl.dispatch();
|
||||||
f.run();
|
f.run();
|
||||||
|
|
@ -2416,11 +2406,11 @@ fn tablet_tool_fractional_scale() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn output_updated_before_x_connection() {
|
fn output_updated_before_x_connection() {
|
||||||
let mut f = TestFixture::new_with_options(SetupOptions::dont_connect_x());
|
let mut f = EarlyTestFixture::new_early_with_options(SetupOptions::default());
|
||||||
let comp = f.compositor();
|
let comp = f.compositor();
|
||||||
let (_, output) = f.new_output(-20, -20);
|
let (_, output) = f.new_output(-20, -20);
|
||||||
|
|
||||||
f.satellite.set_x_connection(FakeXConnection::default());
|
let mut f = f.upgrade_connection(FakeXConnection::default());
|
||||||
|
|
||||||
let window = unsafe { Window::new(1) };
|
let window = unsafe { Window::new(1) };
|
||||||
let (_, surface_id) = f.create_toplevel(&comp, window);
|
let (_, surface_id) = f.create_toplevel(&comp, window);
|
||||||
|
|
|
||||||
|
|
@ -227,10 +227,13 @@ impl XState {
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn server_state_setup(&self, server_state: &mut super::RealServerState) {
|
pub fn server_state_setup(
|
||||||
|
&self,
|
||||||
|
server_state: super::EarlyServerState,
|
||||||
|
) -> super::RealServerState {
|
||||||
let mut c = RealConnection::new(self.connection.clone(), self.atoms.clone());
|
let mut c = RealConnection::new(self.connection.clone(), self.atoms.clone());
|
||||||
c.update_outputs(self.root);
|
c.update_outputs(self.root);
|
||||||
server_state.set_x_connection(c);
|
server_state.upgrade_connection(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_root_property<P: x::PropEl>(&self, property: x::Atom, r#type: x::Atom, data: &[P]) {
|
fn set_root_property<P: x::PropEl>(&self, property: x::Atom, r#type: x::Atom, data: &[P]) {
|
||||||
|
|
@ -1186,15 +1189,14 @@ impl RealConnection {
|
||||||
self.outputs, self.primary_output
|
self.outputs, self.primary_output
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl XConnection for RealConnection {
|
|
||||||
type X11Selection = Selection;
|
|
||||||
|
|
||||||
fn root_window(&self) -> x::Window {
|
fn root_window(&self) -> x::Window {
|
||||||
self.connection.get_setup().roots().next().unwrap().root()
|
self.connection.get_setup().roots().next().unwrap().root()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XConnection for RealConnection {
|
||||||
|
type X11Selection = Selection;
|
||||||
fn set_window_dims(&mut self, window: x::Window, dims: crate::server::PendingSurfaceState) {
|
fn set_window_dims(&mut self, window: x::Window, dims: crate::server::PendingSurfaceState) {
|
||||||
trace!("set window dimensions {window:?} {dims:?}");
|
trace!("set window dimensions {window:?} {dims:?}");
|
||||||
unwrap_or_skip_bad_window!(self.connection.send_and_check_request(&x::ConfigureWindow {
|
unwrap_or_skip_bad_window!(self.connection.send_and_check_request(&x::ConfigureWindow {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue