parent
0a5dddacfd
commit
d3a46b7c8a
8 changed files with 263 additions and 48 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::server::{ObjectEvent, ObjectKey};
|
use crate::server::{ObjectEvent, ObjectKey};
|
||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
use std::sync::mpsc;
|
|
||||||
use wayland_client::protocol::{
|
use wayland_client::protocol::{
|
||||||
wl_buffer::WlBuffer, wl_callback::WlCallback, wl_compositor::WlCompositor,
|
wl_buffer::WlBuffer, wl_callback::WlCallback, wl_compositor::WlCompositor,
|
||||||
wl_keyboard::WlKeyboard, wl_output::WlOutput, wl_pointer::WlPointer, wl_region::WlRegion,
|
wl_keyboard::WlKeyboard, wl_output::WlOutput, wl_pointer::WlPointer, wl_region::WlRegion,
|
||||||
|
|
@ -156,19 +155,6 @@ impl Dispatch<WlCallback, server::wl_callback::WlCallback> for Globals {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dispatch<WlOutput, mpsc::Sender<Event<WlOutput>>> for Globals {
|
|
||||||
fn event(
|
|
||||||
_: &mut Self,
|
|
||||||
_: &WlOutput,
|
|
||||||
event: <WlOutput as Proxy>::Event,
|
|
||||||
data: &mpsc::Sender<Event<WlOutput>>,
|
|
||||||
_: &Connection,
|
|
||||||
_: &QueueHandle<Self>,
|
|
||||||
) {
|
|
||||||
let _ = data.send(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! push_events {
|
macro_rules! push_events {
|
||||||
($type:ident) => {
|
($type:ident) => {
|
||||||
impl Dispatch<$type, ObjectKey> for Globals {
|
impl Dispatch<$type, ObjectKey> for Globals {
|
||||||
|
|
|
||||||
|
|
@ -1103,7 +1103,31 @@ where
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
global_dispatch_with_events!(WlOutput, client::wl_output::WlOutput);
|
impl<C: XConnection> GlobalDispatch<WlOutput, Global> for ServerState<C> {
|
||||||
|
fn bind(
|
||||||
|
state: &mut Self,
|
||||||
|
_: &DisplayHandle,
|
||||||
|
_: &wayland_server::Client,
|
||||||
|
resource: wayland_server::New<WlOutput>,
|
||||||
|
data: &Global,
|
||||||
|
data_init: &mut wayland_server::DataInit<'_, Self>,
|
||||||
|
) {
|
||||||
|
state.objects.insert_with_key(|key| {
|
||||||
|
let server = data_init.init(resource, key);
|
||||||
|
let client = state
|
||||||
|
.clientside
|
||||||
|
.global_list
|
||||||
|
.registry()
|
||||||
|
.bind::<client::wl_output::WlOutput, _, _>(
|
||||||
|
data.name,
|
||||||
|
server.version(),
|
||||||
|
&state.qh,
|
||||||
|
key,
|
||||||
|
);
|
||||||
|
Output::new(client, server).into()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
global_dispatch_with_events!(WlDrmServer, WlDrmClient);
|
global_dispatch_with_events!(WlDrmServer, WlDrmClient);
|
||||||
|
|
||||||
impl<C: XConnection> GlobalDispatch<XwaylandShellV1, ()> for ServerState<C> {
|
impl<C: XConnection> GlobalDispatch<XwaylandShellV1, ()> for ServerState<C> {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use log::{debug, trace, warn};
|
use log::{debug, trace, warn};
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::os::fd::AsFd;
|
use std::os::fd::AsFd;
|
||||||
use wayland_client::{protocol as client, Proxy};
|
use wayland_client::{protocol as client, Proxy};
|
||||||
use wayland_protocols::{
|
use wayland_protocols::{
|
||||||
|
|
@ -150,16 +151,26 @@ impl SurfaceData {
|
||||||
simple_event_shunt! {
|
simple_event_shunt! {
|
||||||
surface, event: client::wl_surface::Event => [
|
surface, event: client::wl_surface::Event => [
|
||||||
Enter { |output| {
|
Enter { |output| {
|
||||||
let Some(object) = &state.get_object_from_client_object::<Output, _>(&output) else {
|
let key: ObjectKey = output.data().copied().unwrap();
|
||||||
|
let Some(object) = state.objects.get_mut(key) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
&object.server
|
let output: &mut Output = object.as_mut();
|
||||||
|
if let Some(win) = self.window {
|
||||||
|
if let Some(data) = state.windows.get(&win) {
|
||||||
|
output.add_surface(self, data.attrs.dims, state.connection.as_mut().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&output.server
|
||||||
}},
|
}},
|
||||||
Leave { |output| {
|
Leave { |output| {
|
||||||
let Some(object) = &state.get_object_from_client_object::<Output, _>(&output) else {
|
let key: ObjectKey = output.data().copied().unwrap();
|
||||||
|
let Some(object) = state.objects.get_mut(key) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
&object.server
|
let output: &mut Output = object.as_mut();
|
||||||
|
output.surfaces.remove(&self.client);
|
||||||
|
&output.server
|
||||||
}},
|
}},
|
||||||
PreferredBufferScale { factor }
|
PreferredBufferScale { factor }
|
||||||
]
|
]
|
||||||
|
|
@ -179,32 +190,36 @@ impl SurfaceData {
|
||||||
if let Some(pending) = xdg.pending.take() {
|
if let Some(pending) = xdg.pending.take() {
|
||||||
let window = state.associated_windows[self.key];
|
let window = state.associated_windows[self.key];
|
||||||
let window = state.windows.get_mut(&window).unwrap();
|
let window = state.windows.get_mut(&window).unwrap();
|
||||||
|
let x = match pending.x {
|
||||||
|
Some(x) => x as i16,
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
let y = match pending.y {
|
||||||
|
Some(y) => y as i16,
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
let width = if pending.width > 0 {
|
let width = if pending.width > 0 {
|
||||||
pending.width as _
|
pending.width as u16
|
||||||
} else {
|
} else {
|
||||||
window.attrs.dims.width
|
window.attrs.dims.width
|
||||||
};
|
};
|
||||||
let height = if pending.height > 0 {
|
let height = if pending.height > 0 {
|
||||||
pending.height as _
|
pending.height as u16
|
||||||
} else {
|
} else {
|
||||||
window.attrs.dims.height
|
window.attrs.dims.height
|
||||||
};
|
};
|
||||||
debug!(
|
debug!("configuring {:?}: {x}x{y}, {width}x{height}", window.window);
|
||||||
"configuring {:?}: {}x{}, {width}x{height}",
|
|
||||||
window.window, pending.x, pending.y
|
|
||||||
);
|
|
||||||
connection.set_window_dims(
|
connection.set_window_dims(
|
||||||
window.window,
|
window.window,
|
||||||
PendingSurfaceState {
|
PendingSurfaceState {
|
||||||
x: pending.x,
|
|
||||||
y: pending.y,
|
|
||||||
width: width as _,
|
width: width as _,
|
||||||
height: height as _,
|
height: height as _,
|
||||||
|
..pending
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
window.attrs.dims = WindowDims {
|
window.attrs.dims = WindowDims {
|
||||||
x: pending.x as _,
|
x,
|
||||||
y: pending.y as _,
|
y,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
};
|
};
|
||||||
|
|
@ -277,8 +292,8 @@ impl SurfaceData {
|
||||||
} => {
|
} => {
|
||||||
trace!("popup configure: {x}x{y}, {width}x{height}");
|
trace!("popup configure: {x}x{y}, {width}x{height}");
|
||||||
self.xdg_mut().unwrap().pending = Some(PendingSurfaceState {
|
self.xdg_mut().unwrap().pending = Some(PendingSurfaceState {
|
||||||
x,
|
x: Some(x),
|
||||||
y,
|
y: Some(y),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
});
|
});
|
||||||
|
|
@ -618,11 +633,78 @@ impl HandleEvent for Touch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Output = GenericObject<WlOutput, client::wl_output::WlOutput>;
|
pub struct Output {
|
||||||
|
pub client: client::wl_output::WlOutput,
|
||||||
|
pub server: WlOutput,
|
||||||
|
surfaces: HashSet<client::wl_surface::WlSurface>,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Output {
|
||||||
|
pub fn new(client: client::wl_output::WlOutput, server: WlOutput) -> Self {
|
||||||
|
Self {
|
||||||
|
client,
|
||||||
|
server,
|
||||||
|
surfaces: HashSet::new(),
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_surface<C: XConnection>(
|
||||||
|
&mut self,
|
||||||
|
surface: &SurfaceData,
|
||||||
|
dims: WindowDims,
|
||||||
|
connection: &mut C,
|
||||||
|
) {
|
||||||
|
self.surfaces.insert(surface.client.clone());
|
||||||
|
let window = surface.window.unwrap();
|
||||||
|
|
||||||
|
debug!("moving surface to {}x{}", self.x, self.y);
|
||||||
|
connection.set_window_dims(
|
||||||
|
window,
|
||||||
|
PendingSurfaceState {
|
||||||
|
x: Some(self.x),
|
||||||
|
y: Some(self.y),
|
||||||
|
width: dims.width as _,
|
||||||
|
height: dims.height as _,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
impl HandleEvent for Output {
|
impl HandleEvent for Output {
|
||||||
type Event = client::wl_output::Event;
|
type Event = client::wl_output::Event;
|
||||||
|
|
||||||
fn handle_event<C: XConnection>(&mut self, event: Self::Event, _: &mut ServerState<C>) {
|
fn handle_event<C: XConnection>(&mut self, event: Self::Event, state: &mut ServerState<C>) {
|
||||||
|
if let client::wl_output::Event::Geometry { x, y, .. } = event {
|
||||||
|
debug!("moving output to {x}x{y}");
|
||||||
|
self.x = x;
|
||||||
|
self.y = y;
|
||||||
|
self.surfaces.retain(|surface| {
|
||||||
|
let Some(data) = state.get_object_from_client_object::<SurfaceData, _>(surface)
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let window = data.window.as_ref().copied().unwrap();
|
||||||
|
let Some(win_data) = state.windows.get(&window) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
state.connection.as_mut().unwrap().set_window_dims(
|
||||||
|
window,
|
||||||
|
PendingSurfaceState {
|
||||||
|
x: Some(x),
|
||||||
|
y: Some(y),
|
||||||
|
width: win_data.attrs.dims.width as _,
|
||||||
|
height: win_data.attrs.dims.height as _,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
simple_event_shunt! {
|
simple_event_shunt! {
|
||||||
self.server, event: client::wl_output::Event => [
|
self.server, event: client::wl_output::Event => [
|
||||||
Name { name },
|
Name { name },
|
||||||
|
|
|
||||||
|
|
@ -937,8 +937,8 @@ impl<C: XConnection> ServerState<C> {
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct PendingSurfaceState {
|
pub struct PendingSurfaceState {
|
||||||
pub x: i32,
|
pub x: Option<i32>,
|
||||||
pub y: i32,
|
pub y: Option<i32>,
|
||||||
pub width: i32,
|
pub width: i32,
|
||||||
pub height: i32,
|
pub height: i32,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -191,8 +191,8 @@ impl super::XConnection for FakeXConnection {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn set_window_dims(&mut self, window: Window, state: super::PendingSurfaceState) {
|
fn set_window_dims(&mut self, window: Window, state: super::PendingSurfaceState) {
|
||||||
self.window(window).dims = WindowDims {
|
self.window(window).dims = WindowDims {
|
||||||
x: state.x as _,
|
x: state.x.unwrap_or(0) as _,
|
||||||
y: state.y as _,
|
y: state.y.unwrap_or(0) as _,
|
||||||
width: state.width as _,
|
width: state.width as _,
|
||||||
height: state.height as _,
|
height: state.height as _,
|
||||||
};
|
};
|
||||||
|
|
@ -699,6 +699,8 @@ fn pass_through_globals() {
|
||||||
use wayland_client::protocol::wl_output::WlOutput;
|
use wayland_client::protocol::wl_output::WlOutput;
|
||||||
|
|
||||||
let mut f = TestFixture::new();
|
let mut f = TestFixture::new();
|
||||||
|
f.testwl.new_output(0, 0);
|
||||||
|
f.run();
|
||||||
|
|
||||||
const fn check<T: Proxy>() {}
|
const fn check<T: Proxy>() {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -782,14 +782,21 @@ impl super::XConnection for Arc<xcb::Connection> {
|
||||||
|
|
||||||
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!("reconfiguring window {window:?}");
|
trace!("reconfiguring window {window:?}");
|
||||||
unwrap_or_skip_bad_window!(self.send_and_check_request(&x::ConfigureWindow {
|
let mut vals = vec![
|
||||||
window,
|
|
||||||
value_list: &[
|
|
||||||
x::ConfigWindow::X(dims.x),
|
|
||||||
x::ConfigWindow::Y(dims.y),
|
|
||||||
x::ConfigWindow::Width(dims.width as _),
|
x::ConfigWindow::Width(dims.width as _),
|
||||||
x::ConfigWindow::Height(dims.height as _),
|
x::ConfigWindow::Height(dims.height as _),
|
||||||
],
|
];
|
||||||
|
if let Some(x) = dims.x {
|
||||||
|
vals.push(x::ConfigWindow::X(x));
|
||||||
|
}
|
||||||
|
if let Some(y) = dims.y {
|
||||||
|
vals.push(x::ConfigWindow::Y(y));
|
||||||
|
}
|
||||||
|
vals.sort();
|
||||||
|
|
||||||
|
unwrap_or_skip_bad_window!(self.send_and_check_request(&x::ConfigureWindow {
|
||||||
|
window,
|
||||||
|
value_list: &vals
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -870,3 +870,42 @@ fn copy_from_wayland() {
|
||||||
assert_eq!(val, data);
|
assert_eq!(val, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this test doesn't actually match real behavior for some reason...
|
||||||
|
#[test]
|
||||||
|
fn different_output_position() {
|
||||||
|
let mut f = Fixture::new();
|
||||||
|
let mut connection = Connection::new(&f.display);
|
||||||
|
|
||||||
|
let window = connection.new_window(connection.root, 0, 0, 200, 200, false);
|
||||||
|
connection.map_window(window);
|
||||||
|
f.wait_and_dispatch();
|
||||||
|
let surface = f
|
||||||
|
.testwl
|
||||||
|
.last_created_surface_id()
|
||||||
|
.expect("No surface created!");
|
||||||
|
f.configure_and_verify_new_toplevel(&mut connection, window, surface);
|
||||||
|
|
||||||
|
f.testwl.new_output(0, 0);
|
||||||
|
f.wait_and_dispatch();
|
||||||
|
let output = f.testwl.last_created_output();
|
||||||
|
f.testwl.move_surface_to_output(surface, output);
|
||||||
|
f.testwl.move_pointer_to(surface, 10.0, 10.0);
|
||||||
|
f.wait_and_dispatch();
|
||||||
|
let reply = connection.get_reply(&x::QueryPointer { window });
|
||||||
|
assert_eq!(reply.same_screen(), true);
|
||||||
|
assert_eq!(reply.win_x(), 10);
|
||||||
|
assert_eq!(reply.win_y(), 10);
|
||||||
|
|
||||||
|
f.testwl.new_output(100, 0);
|
||||||
|
f.wait_and_dispatch();
|
||||||
|
let output = f.testwl.last_created_output();
|
||||||
|
f.testwl.move_surface_to_output(surface, output);
|
||||||
|
f.testwl.move_pointer_to(surface, 150.0, 12.0);
|
||||||
|
f.wait_and_dispatch();
|
||||||
|
let reply = connection.get_reply(&x::QueryPointer { window });
|
||||||
|
println!("reply: {reply:?}");
|
||||||
|
assert_eq!(reply.same_screen(), true);
|
||||||
|
assert_eq!(reply.win_x(), 150);
|
||||||
|
assert_eq!(reply.win_y(), 12);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ use wayland_server::{
|
||||||
wl_data_offer::{self, WlDataOffer},
|
wl_data_offer::{self, WlDataOffer},
|
||||||
wl_data_source::{self, WlDataSource},
|
wl_data_source::{self, WlDataSource},
|
||||||
wl_keyboard::{self, WlKeyboard},
|
wl_keyboard::{self, WlKeyboard},
|
||||||
wl_output::WlOutput,
|
wl_output::{self, WlOutput},
|
||||||
wl_pointer::{self, WlPointer},
|
wl_pointer::{self, WlPointer},
|
||||||
wl_seat::{self, WlSeat},
|
wl_seat::{self, WlSeat},
|
||||||
wl_shm::WlShm,
|
wl_shm::WlShm,
|
||||||
|
|
@ -155,6 +155,7 @@ struct DataSourceData {
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
surfaces: HashMap<SurfaceId, SurfaceData>,
|
surfaces: HashMap<SurfaceId, SurfaceData>,
|
||||||
|
outputs: Vec<WlOutput>,
|
||||||
positioners: HashMap<PositionerId, PositionerState>,
|
positioners: HashMap<PositionerId, PositionerState>,
|
||||||
buffers: HashSet<WlBuffer>,
|
buffers: HashSet<WlBuffer>,
|
||||||
begin: Instant,
|
begin: Instant,
|
||||||
|
|
@ -172,6 +173,7 @@ impl Default for State {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
surfaces: Default::default(),
|
surfaces: Default::default(),
|
||||||
|
outputs: Default::default(),
|
||||||
buffers: Default::default(),
|
buffers: Default::default(),
|
||||||
positioners: Default::default(),
|
positioners: Default::default(),
|
||||||
begin: Instant::now(),
|
begin: Instant::now(),
|
||||||
|
|
@ -286,7 +288,6 @@ impl Server {
|
||||||
dh.create_global::<State, XdgWmBase, _>(6, ());
|
dh.create_global::<State, XdgWmBase, _>(6, ());
|
||||||
dh.create_global::<State, WlSeat, _>(5, ());
|
dh.create_global::<State, WlSeat, _>(5, ());
|
||||||
dh.create_global::<State, WlDataDeviceManager, _>(3, ());
|
dh.create_global::<State, WlDataDeviceManager, _>(3, ());
|
||||||
global_noop!(WlOutput);
|
|
||||||
global_noop!(ZwpLinuxDmabufV1);
|
global_noop!(ZwpLinuxDmabufV1);
|
||||||
global_noop!(ZwpRelativePointerManagerV1);
|
global_noop!(ZwpRelativePointerManagerV1);
|
||||||
global_noop!(ZxdgOutputManagerV1);
|
global_noop!(ZxdgOutputManagerV1);
|
||||||
|
|
@ -382,6 +383,15 @@ impl Server {
|
||||||
self.state.last_surface_id
|
self.state.last_surface_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
pub fn last_created_output(&self) -> WlOutput {
|
||||||
|
self.state
|
||||||
|
.outputs
|
||||||
|
.last()
|
||||||
|
.expect("No outputs created!")
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_object<T: Resource + 'static>(
|
pub fn get_object<T: Resource + 'static>(
|
||||||
&self,
|
&self,
|
||||||
id: SurfaceId,
|
id: SurfaceId,
|
||||||
|
|
@ -476,6 +486,27 @@ impl Server {
|
||||||
dev.selection(Some(&offer));
|
dev.selection(Some(&offer));
|
||||||
self.display.flush_clients().unwrap();
|
self.display.flush_clients().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
pub fn move_pointer_to(&mut self, surface: SurfaceId, x: f64, y: f64) {
|
||||||
|
let pointer = self.state.pointer.as_ref().expect("No pointer created");
|
||||||
|
let data = self.state.surfaces.get(&surface).expect("No such surface");
|
||||||
|
|
||||||
|
pointer.enter(24, &data.surface, x, y);
|
||||||
|
pointer.frame();
|
||||||
|
self.display.flush_clients().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_output(&mut self, x: i32, y: i32) {
|
||||||
|
self.dh.create_global::<State, WlOutput, _>(4, (x, y));
|
||||||
|
self.display.flush_clients().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn move_surface_to_output(&mut self, surface: SurfaceId, output: WlOutput) {
|
||||||
|
let data = self.state.surfaces.get(&surface).expect("No such surface");
|
||||||
|
data.surface.enter(&output);
|
||||||
|
self.display.flush_clients().unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PasteDataResolver {
|
pub struct PasteDataResolver {
|
||||||
|
|
@ -527,6 +558,46 @@ simple_global_dispatch!(WlShm);
|
||||||
simple_global_dispatch!(WlCompositor);
|
simple_global_dispatch!(WlCompositor);
|
||||||
simple_global_dispatch!(XdgWmBase);
|
simple_global_dispatch!(XdgWmBase);
|
||||||
|
|
||||||
|
impl GlobalDispatch<WlOutput, (i32, i32)> for State {
|
||||||
|
fn bind(
|
||||||
|
state: &mut Self,
|
||||||
|
_: &DisplayHandle,
|
||||||
|
_: &Client,
|
||||||
|
resource: wayland_server::New<WlOutput>,
|
||||||
|
&(x, y): &(i32, i32),
|
||||||
|
data_init: &mut wayland_server::DataInit<'_, Self>,
|
||||||
|
) {
|
||||||
|
let output = data_init.init(resource, ());
|
||||||
|
output.geometry(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
wl_output::Subpixel::None,
|
||||||
|
"xwls".to_string(),
|
||||||
|
"fake monitor".to_string(),
|
||||||
|
wl_output::Transform::Normal,
|
||||||
|
);
|
||||||
|
output.mode(wl_output::Mode::Current, 1000, 1000, 0);
|
||||||
|
output.done();
|
||||||
|
state.outputs.push(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch<WlOutput, ()> for State {
|
||||||
|
fn request(
|
||||||
|
_: &mut Self,
|
||||||
|
_: &Client,
|
||||||
|
_: &WlOutput,
|
||||||
|
_: <WlOutput as Resource>::Request,
|
||||||
|
_: &(),
|
||||||
|
_: &DisplayHandle,
|
||||||
|
_: &mut wayland_server::DataInit<'_, Self>,
|
||||||
|
) {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GlobalDispatch<WlDataDeviceManager, ()> for State {
|
impl GlobalDispatch<WlDataDeviceManager, ()> for State {
|
||||||
fn bind(
|
fn bind(
|
||||||
state: &mut Self,
|
state: &mut Self,
|
||||||
|
|
@ -688,8 +759,11 @@ impl Dispatch<WlPointer, ()> for State {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
data.role.replace(SurfaceRole::Cursor).is_none(),
|
matches!(
|
||||||
"Surface already had a role!"
|
data.role.replace(SurfaceRole::Cursor),
|
||||||
|
None | Some(SurfaceRole::Cursor)
|
||||||
|
),
|
||||||
|
"Surface already had a non cursor role!"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1144,6 +1218,7 @@ impl Dispatch<WlSurface, ()> for State {
|
||||||
.remove(&SurfaceId(resource.id().protocol_id()));
|
.remove(&SurfaceId(resource.id().protocol_id()));
|
||||||
}
|
}
|
||||||
SetInputRegion { .. } => {}
|
SetInputRegion { .. } => {}
|
||||||
|
SetBufferScale { .. } => {}
|
||||||
other => todo!("unhandled request {other:?}"),
|
other => todo!("unhandled request {other:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue