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::{
|
protocols::{
|
||||||
ObjectInterface,
|
ObjectInterface,
|
||||||
linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
|
linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
|
||||||
|
viewporter::wp_viewporter::WpViewporter,
|
||||||
wayland::{
|
wayland::{
|
||||||
|
wl_compositor::WlCompositor,
|
||||||
wl_registry::{WlRegistry, WlRegistryHandler},
|
wl_registry::{WlRegistry, WlRegistryHandler},
|
||||||
wl_shm::WlShm,
|
wl_shm::WlShm,
|
||||||
},
|
},
|
||||||
|
|
@ -47,11 +49,17 @@ impl ClientWlRegistry {
|
||||||
impl WlRegistryHandler for ClientWlRegistry {
|
impl WlRegistryHandler for ClientWlRegistry {
|
||||||
fn handle_bind(&mut self, slf: &Rc<WlRegistry>, name: u32, id: Rc<dyn Object>) {
|
fn handle_bind(&mut self, slf: &Rc<WlRegistry>, name: u32, id: Rc<dyn Object>) {
|
||||||
match id.interface() {
|
match id.interface() {
|
||||||
|
WlCompositor::INTERFACE => id
|
||||||
|
.downcast::<WlCompositor>()
|
||||||
|
.set_handler(xdg::ClientWlCompositor),
|
||||||
XdgWmBase::INTERFACE => id
|
XdgWmBase::INTERFACE => id
|
||||||
.downcast::<XdgWmBase>()
|
.downcast::<XdgWmBase>()
|
||||||
.set_handler(xdg::ClientXdgWmBase {
|
.set_handler(xdg::ClientXdgWmBase {
|
||||||
globals: self.globals.clone(),
|
globals: self.globals.clone(),
|
||||||
}),
|
}),
|
||||||
|
WpViewporter::INTERFACE => id
|
||||||
|
.downcast::<WpViewporter>()
|
||||||
|
.set_handler(xdg::ClientWpViewporter),
|
||||||
ZxdgDecorationManagerV1::INTERFACE => {
|
ZxdgDecorationManagerV1::INTERFACE => {
|
||||||
id.set_forward_to_server(false);
|
id.set_forward_to_server(false);
|
||||||
id.downcast::<ZxdgDecorationManagerV1>()
|
id.downcast::<ZxdgDecorationManagerV1>()
|
||||||
|
|
|
||||||
135
src/xdg.rs
135
src/xdg.rs
|
|
@ -1,10 +1,16 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use wl_proxy::{
|
use wl_proxy::{
|
||||||
|
fixed::Fixed,
|
||||||
object::{ObjectCoreApi, ObjectUtils},
|
object::{ObjectCoreApi, ObjectUtils},
|
||||||
protocols::{
|
protocols::{
|
||||||
|
viewporter::{
|
||||||
|
wp_viewport::{WpViewport, WpViewportHandler},
|
||||||
|
wp_viewporter::{WpViewporter, WpViewporterHandler},
|
||||||
|
},
|
||||||
wayland::{
|
wayland::{
|
||||||
wl_buffer::WlBuffer,
|
wl_buffer::WlBuffer,
|
||||||
|
wl_compositor::{WlCompositor, WlCompositorHandler},
|
||||||
wl_output::{WlOutput, WlOutputTransform},
|
wl_output::{WlOutput, WlOutputTransform},
|
||||||
wl_surface::{WlSurface, WlSurfaceHandler},
|
wl_surface::{WlSurface, WlSurfaceHandler},
|
||||||
},
|
},
|
||||||
|
|
@ -32,10 +38,25 @@ use crate::{
|
||||||
util::{Bounds, Edges},
|
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 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 transform: Option<WlOutputTransform>,
|
||||||
pub scale: Option<i32>,
|
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 {
|
impl WlSurfaceHandler for ClientWlSurface {
|
||||||
|
|
@ -56,28 +77,9 @@ impl WlSurfaceHandler for ClientWlSurface {
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
) {
|
) {
|
||||||
let surf_handler = self.xdg_surface.get_handler_ref::<ClientXdgSurface>();
|
|
||||||
if let Some(buffer) = buffer {
|
if let Some(buffer) = buffer {
|
||||||
if let Ok(buf_handler) = buffer.try_get_handler_ref::<client_buffer::ClientWlBuffer>() {
|
if let Ok(buf_handler) = buffer.try_get_handler_ref::<client_buffer::ClientWlBuffer>() {
|
||||||
if let Some(deco) = surf_handler.deco.as_ref() {
|
self.buffer_size = Some((buf_handler.width, buf_handler.height));
|
||||||
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");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
log::warn!("surface {slf:?} buffer with unknown size {buffer:?}");
|
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>) {
|
fn handle_commit(&mut self, slf: &Rc<WlSurface>) {
|
||||||
log::debug!("commit {slf:?}");
|
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(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();
|
deco.handle_commit().unwrap();
|
||||||
}
|
}
|
||||||
slf.send_commit();
|
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;
|
pub struct ClientZxdgDecorationManagerV1;
|
||||||
|
|
||||||
impl ZxdgDecorationManagerV1Handler for ClientZxdgDecorationManagerV1 {
|
impl ZxdgDecorationManagerV1Handler for ClientZxdgDecorationManagerV1 {
|
||||||
|
|
@ -156,11 +240,8 @@ impl XdgWmBaseHandler for ClientXdgWmBase {
|
||||||
id: &Rc<XdgSurface>,
|
id: &Rc<XdgSurface>,
|
||||||
surface: &Rc<WlSurface>,
|
surface: &Rc<WlSurface>,
|
||||||
) {
|
) {
|
||||||
surface.set_handler(ClientWlSurface {
|
let mut surf_handler = surface.get_handler_mut::<ClientWlSurface>();
|
||||||
xdg_surface: id.clone(),
|
surf_handler.xdg_surface = Some(id.clone());
|
||||||
scale: None,
|
|
||||||
transform: None,
|
|
||||||
});
|
|
||||||
id.set_handler(ClientXdgSurface {
|
id.set_handler(ClientXdgSurface {
|
||||||
deco: None,
|
deco: None,
|
||||||
globals: self.globals.clone(),
|
globals: self.globals.clone(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue