Handle clients that support fractional scaling but don't set geometry
Goxel is a great example
This commit is contained in:
parent
207529a185
commit
049eb03387
2 changed files with 116 additions and 27 deletions
|
|
@ -8,7 +8,9 @@ use wl_proxy::{
|
|||
protocols::{
|
||||
ObjectInterface,
|
||||
linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
|
||||
viewporter::wp_viewporter::WpViewporter,
|
||||
wayland::{
|
||||
wl_compositor::WlCompositor,
|
||||
wl_registry::{WlRegistry, WlRegistryHandler},
|
||||
wl_shm::WlShm,
|
||||
},
|
||||
|
|
@ -47,11 +49,17 @@ impl ClientWlRegistry {
|
|||
impl WlRegistryHandler for ClientWlRegistry {
|
||||
fn handle_bind(&mut self, slf: &Rc<WlRegistry>, name: u32, id: Rc<dyn Object>) {
|
||||
match id.interface() {
|
||||
WlCompositor::INTERFACE => id
|
||||
.downcast::<WlCompositor>()
|
||||
.set_handler(xdg::ClientWlCompositor),
|
||||
XdgWmBase::INTERFACE => id
|
||||
.downcast::<XdgWmBase>()
|
||||
.set_handler(xdg::ClientXdgWmBase {
|
||||
globals: self.globals.clone(),
|
||||
}),
|
||||
WpViewporter::INTERFACE => id
|
||||
.downcast::<WpViewporter>()
|
||||
.set_handler(xdg::ClientWpViewporter),
|
||||
ZxdgDecorationManagerV1::INTERFACE => {
|
||||
id.set_forward_to_server(false);
|
||||
id.downcast::<ZxdgDecorationManagerV1>()
|
||||
|
|
|
|||
135
src/xdg.rs
135
src/xdg.rs
|
|
@ -1,10 +1,16 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use wl_proxy::{
|
||||
fixed::Fixed,
|
||||
object::{ObjectCoreApi, ObjectUtils},
|
||||
protocols::{
|
||||
viewporter::{
|
||||
wp_viewport::{WpViewport, WpViewportHandler},
|
||||
wp_viewporter::{WpViewporter, WpViewporterHandler},
|
||||
},
|
||||
wayland::{
|
||||
wl_buffer::WlBuffer,
|
||||
wl_compositor::{WlCompositor, WlCompositorHandler},
|
||||
wl_output::{WlOutput, WlOutputTransform},
|
||||
wl_surface::{WlSurface, WlSurfaceHandler},
|
||||
},
|
||||
|
|
@ -32,10 +38,25 @@ use crate::{
|
|||
util::{Bounds, Edges},
|
||||
};
|
||||
|
||||
pub struct ClientWlCompositor;
|
||||
|
||||
impl WlCompositorHandler for ClientWlCompositor {
|
||||
fn handle_create_surface(&mut self, slf: &Rc<WlCompositor>, id: &Rc<WlSurface>) {
|
||||
id.set_handler(ClientWlSurface::default());
|
||||
slf.send_create_surface(id);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ClientWlSurface {
|
||||
pub xdg_surface: Rc<XdgSurface>,
|
||||
pub xdg_surface: Option<Rc<XdgSurface>>,
|
||||
|
||||
// All of this is buffered next state, we don't reference past state here
|
||||
pub transform: Option<WlOutputTransform>,
|
||||
pub scale: Option<i32>,
|
||||
pub buffer_size: Option<(i32, i32)>,
|
||||
pub wp_src_size: Option<(i32, i32)>,
|
||||
pub wp_dest_size: Option<(i32, i32)>,
|
||||
}
|
||||
|
||||
impl WlSurfaceHandler for ClientWlSurface {
|
||||
|
|
@ -56,28 +77,9 @@ impl WlSurfaceHandler for ClientWlSurface {
|
|||
x: i32,
|
||||
y: i32,
|
||||
) {
|
||||
let surf_handler = self.xdg_surface.get_handler_ref::<ClientXdgSurface>();
|
||||
if let Some(buffer) = buffer {
|
||||
if let Ok(buf_handler) = buffer.try_get_handler_ref::<client_buffer::ClientWlBuffer>() {
|
||||
if let Some(deco) = surf_handler.deco.as_ref() {
|
||||
let mut width = buf_handler.width;
|
||||
let mut height = buf_handler.height;
|
||||
if let Some(scale) = self.scale {
|
||||
width /= scale;
|
||||
height /= scale;
|
||||
}
|
||||
if let Some(transform) = self.transform
|
||||
&& (transform == WlOutputTransform::_90
|
||||
|| transform == WlOutputTransform::_270
|
||||
|| transform == WlOutputTransform::FLIPPED_270
|
||||
|| transform == WlOutputTransform::FLIPPED_270)
|
||||
{
|
||||
std::mem::swap(&mut width, &mut height);
|
||||
}
|
||||
deco.handle_intrinsic_size(width, height);
|
||||
} else {
|
||||
log::debug!("surface {slf:?} buffer attach before deco");
|
||||
}
|
||||
self.buffer_size = Some((buf_handler.width, buf_handler.height));
|
||||
} else {
|
||||
log::warn!("surface {slf:?} buffer with unknown size {buffer:?}");
|
||||
}
|
||||
|
|
@ -89,14 +91,96 @@ impl WlSurfaceHandler for ClientWlSurface {
|
|||
|
||||
fn handle_commit(&mut self, slf: &Rc<WlSurface>) {
|
||||
log::debug!("commit {slf:?}");
|
||||
let surf_handler = self.xdg_surface.get_handler_ref::<ClientXdgSurface>();
|
||||
let Some(ref xdg_surface) = self.xdg_surface else {
|
||||
// probably a cursor
|
||||
slf.send_commit();
|
||||
return;
|
||||
};
|
||||
let surf_handler = xdg_surface.get_handler_ref::<ClientXdgSurface>();
|
||||
if let Some(deco) = surf_handler.deco.as_ref() {
|
||||
if let Some((width, height)) = self.wp_dest_size {
|
||||
deco.handle_intrinsic_size(width, height);
|
||||
} else if let Some((width, height)) = self.wp_src_size {
|
||||
// "If the source rectangle is set and the destination size is not set,
|
||||
// [..] the surface size becomes the source rectangle size"
|
||||
deco.handle_intrinsic_size(width, height);
|
||||
} else if let Some((mut width, mut height)) = self.buffer_size {
|
||||
if let Some(transform) = self.transform
|
||||
&& (transform == WlOutputTransform::_90
|
||||
|| transform == WlOutputTransform::_270
|
||||
|| transform == WlOutputTransform::FLIPPED_270
|
||||
|| transform == WlOutputTransform::FLIPPED_270)
|
||||
{
|
||||
std::mem::swap(&mut width, &mut height);
|
||||
}
|
||||
if let Some(scale) = self.scale {
|
||||
width /= scale;
|
||||
height /= scale;
|
||||
}
|
||||
deco.handle_intrinsic_size(width, height);
|
||||
}
|
||||
deco.handle_commit().unwrap();
|
||||
}
|
||||
slf.send_commit();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientWpViewporter;
|
||||
|
||||
impl WpViewporterHandler for ClientWpViewporter {
|
||||
fn handle_get_viewport(
|
||||
&mut self,
|
||||
slf: &Rc<WpViewporter>,
|
||||
id: &Rc<WpViewport>,
|
||||
surface: &Rc<WlSurface>,
|
||||
) {
|
||||
id.set_handler(ClientWpViewport {
|
||||
surface: surface.clone(),
|
||||
});
|
||||
slf.send_get_viewport(id, surface);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientWpViewport {
|
||||
surface: Rc<WlSurface>,
|
||||
}
|
||||
|
||||
impl WpViewportHandler for ClientWpViewport {
|
||||
fn handle_destroy(&mut self, slf: &Rc<WpViewport>) {
|
||||
let mut surf_handler = self.surface.get_handler_mut::<ClientWlSurface>();
|
||||
surf_handler.wp_src_size = None;
|
||||
surf_handler.wp_dest_size = None;
|
||||
slf.send_destroy();
|
||||
}
|
||||
|
||||
fn handle_set_source(
|
||||
&mut self,
|
||||
slf: &Rc<WpViewport>,
|
||||
x: Fixed,
|
||||
y: Fixed,
|
||||
width: Fixed,
|
||||
height: Fixed,
|
||||
) {
|
||||
log::debug!(
|
||||
"surface {:?} WP src {width}x{height} @ {x},{y}",
|
||||
self.surface
|
||||
);
|
||||
let mut surf_handler = self.surface.get_handler_mut::<ClientWlSurface>();
|
||||
surf_handler.wp_src_size = Some((
|
||||
width.to_i32_round_towards_nearest(),
|
||||
height.to_i32_round_towards_nearest(),
|
||||
));
|
||||
slf.send_set_source(x, y, width, height);
|
||||
}
|
||||
|
||||
fn handle_set_destination(&mut self, slf: &Rc<WpViewport>, width: i32, height: i32) {
|
||||
log::debug!("surface {:?} WP dest {width}x{height}", self.surface);
|
||||
let mut surf_handler = self.surface.get_handler_mut::<ClientWlSurface>();
|
||||
surf_handler.wp_dest_size = Some((width, height));
|
||||
slf.send_set_destination(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientZxdgDecorationManagerV1;
|
||||
|
||||
impl ZxdgDecorationManagerV1Handler for ClientZxdgDecorationManagerV1 {
|
||||
|
|
@ -156,11 +240,8 @@ impl XdgWmBaseHandler for ClientXdgWmBase {
|
|||
id: &Rc<XdgSurface>,
|
||||
surface: &Rc<WlSurface>,
|
||||
) {
|
||||
surface.set_handler(ClientWlSurface {
|
||||
xdg_surface: id.clone(),
|
||||
scale: None,
|
||||
transform: None,
|
||||
});
|
||||
let mut surf_handler = surface.get_handler_mut::<ClientWlSurface>();
|
||||
surf_handler.xdg_surface = Some(id.clone());
|
||||
id.set_handler(ClientXdgSurface {
|
||||
deco: None,
|
||||
globals: self.globals.clone(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue