Add synthetic xdg-decoration global for the client
For now, handle SSD preference by drawing a blank title bar (actual impl coming later)
This commit is contained in:
parent
3da5fac131
commit
a5dbec759f
3 changed files with 119 additions and 11 deletions
31
src/deco.rs
31
src/deco.rs
|
|
@ -26,6 +26,7 @@ use crate::{
|
|||
#[derive(Default, Debug, Clone, PartialEq)]
|
||||
struct DecoParams {
|
||||
has_geometry: bool,
|
||||
prefers_ssd: bool,
|
||||
is_active: bool,
|
||||
bounds: Bounds,
|
||||
restricted_edges: Edges<bool>,
|
||||
|
|
@ -34,7 +35,6 @@ struct DecoParams {
|
|||
pub struct Deco {
|
||||
last_params: RefCell<DecoParams>,
|
||||
next_params: RefCell<DecoParams>,
|
||||
top_size: i32,
|
||||
border_size: i32,
|
||||
|
||||
wl_surface: Rc<WlSurface>,
|
||||
|
|
@ -133,6 +133,15 @@ impl DecoSurface {
|
|||
}
|
||||
|
||||
impl Deco {
|
||||
fn top_size(&self) -> i32 {
|
||||
let params = self.last_params.borrow();
|
||||
if params.prefers_ssd {
|
||||
self.border_size + 24
|
||||
} else {
|
||||
self.border_size
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
host_surface: &Rc<WlSurface>,
|
||||
toplevel: &Rc<XdgToplevel>,
|
||||
|
|
@ -151,7 +160,6 @@ impl Deco {
|
|||
let deco = Rc::new(Deco {
|
||||
last_params: RefCell::new(Default::default()),
|
||||
next_params: RefCell::new(Default::default()),
|
||||
top_size: args.thickness as i32, // TODO: title
|
||||
border_size: args.thickness as i32,
|
||||
wl_surface: wl_surface.clone(),
|
||||
subsurface,
|
||||
|
|
@ -200,8 +208,8 @@ impl Deco {
|
|||
height,
|
||||
};
|
||||
let width = width + self.border_size * 2;
|
||||
let height = height + self.top_size + self.border_size;
|
||||
(x - self.border_size, y - self.top_size, width, height)
|
||||
let height = height + self.top_size() + self.border_size;
|
||||
(x - self.border_size, y - self.top_size(), width, height)
|
||||
}
|
||||
|
||||
pub fn set_restricted_edges(&self, edges: Edges<bool>) {
|
||||
|
|
@ -214,6 +222,11 @@ impl Deco {
|
|||
params.is_active = is_active;
|
||||
}
|
||||
|
||||
pub fn set_prefers_ssd(&self, prefers_ssd: bool) {
|
||||
let mut params = self.next_params.borrow_mut();
|
||||
params.prefers_ssd = prefers_ssd;
|
||||
}
|
||||
|
||||
pub fn handle_commit(&self) -> eyre::Result<()> {
|
||||
self.draw()
|
||||
}
|
||||
|
|
@ -221,19 +234,19 @@ impl Deco {
|
|||
pub fn transform_configure(&self, width: i32, height: i32) -> (i32, i32) {
|
||||
(
|
||||
width - self.border_size * 2,
|
||||
height - self.top_size - self.border_size,
|
||||
height - self.top_size() - self.border_size,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn transform_size(&self, width: i32, height: i32) -> (i32, i32) {
|
||||
(
|
||||
width + self.border_size * 2,
|
||||
height + self.top_size + self.border_size,
|
||||
height + self.top_size() + self.border_size,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn transform_anchor(&self, x: i32, y: i32) -> (i32, i32) {
|
||||
(x + self.border_size, y + self.top_size)
|
||||
(x + self.border_size, y + self.top_size())
|
||||
}
|
||||
|
||||
fn draw(&self) -> eyre::Result<()> {
|
||||
|
|
@ -273,13 +286,13 @@ impl Deco {
|
|||
self.wl_surface.send_damage_buffer(0, 0, width, height);
|
||||
let input_region = self.globals.wl_compositor.new_send_create_region();
|
||||
input_region.set_forward_to_client(false);
|
||||
input_region.send_add(0, 0, width, self.top_size);
|
||||
input_region.send_add(0, 0, width, self.top_size());
|
||||
input_region.send_add(0, 0, self.border_size, height);
|
||||
input_region.send_add(width - self.border_size, 0, self.border_size, height);
|
||||
input_region.send_add(0, height - self.border_size, width, self.border_size);
|
||||
self.wl_surface.send_set_input_region(Some(&input_region));
|
||||
self.subsurface
|
||||
.send_set_position(bounds.x - self.border_size, bounds.y - self.top_size);
|
||||
.send_set_position(bounds.x - self.border_size, bounds.y - self.top_size());
|
||||
self.wl_surface.send_commit();
|
||||
// let _ = self.globals.wl_display.new_send_sync();
|
||||
Ok(())
|
||||
|
|
|
|||
42
src/main.rs
42
src/main.rs
|
|
@ -3,13 +3,16 @@ use std::{process::Command, rc::Rc, sync::OnceLock};
|
|||
use clap::{CommandFactory, Parser};
|
||||
use wl_proxy::{
|
||||
baseline::Baseline,
|
||||
global_mapper::GlobalMapper,
|
||||
object::{ConcreteObject, Object, ObjectCoreApi, ObjectRcUtils},
|
||||
protocols::{
|
||||
ObjectInterface,
|
||||
linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
|
||||
wayland::{
|
||||
wl_registry::{WlRegistry, WlRegistryHandler},
|
||||
wl_shm::WlShm,
|
||||
},
|
||||
xdg_decoration_unstable_v1::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1,
|
||||
xdg_shell::xdg_wm_base::XdgWmBase,
|
||||
},
|
||||
simple::{SimpleCommandExt, SimpleProxy},
|
||||
|
|
@ -27,12 +30,16 @@ mod xdg;
|
|||
|
||||
struct ClientWlRegistry {
|
||||
globals: Rc<Globals>,
|
||||
globals_requested: bool,
|
||||
mapper: GlobalMapper,
|
||||
}
|
||||
|
||||
impl ClientWlRegistry {
|
||||
fn new(globals: &Rc<Globals>) -> Self {
|
||||
Self {
|
||||
globals: globals.clone(),
|
||||
globals_requested: false,
|
||||
mapper: GlobalMapper::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +52,12 @@ impl WlRegistryHandler for ClientWlRegistry {
|
|||
.set_handler(xdg::ClientXdgWmBase {
|
||||
globals: self.globals.clone(),
|
||||
}),
|
||||
ZxdgDecorationManagerV1::INTERFACE => {
|
||||
id.set_forward_to_server(false);
|
||||
id.downcast::<ZxdgDecorationManagerV1>()
|
||||
.set_handler(xdg::ClientZxdgDecorationManagerV1);
|
||||
return;
|
||||
}
|
||||
WlShm::INTERFACE => id
|
||||
.downcast::<WlShm>()
|
||||
.set_handler(client_buffer::ClientWlShm),
|
||||
|
|
@ -53,7 +66,34 @@ impl WlRegistryHandler for ClientWlRegistry {
|
|||
.set_handler(client_buffer::ClientZwpLinuxDmabufV1),
|
||||
_ => {}
|
||||
}
|
||||
slf.send_bind(name, id);
|
||||
self.mapper.forward_bind(slf, name, &id);
|
||||
}
|
||||
|
||||
fn handle_global(
|
||||
&mut self,
|
||||
slf: &Rc<WlRegistry>,
|
||||
name: u32,
|
||||
interface: ObjectInterface,
|
||||
version: u32,
|
||||
) {
|
||||
use ObjectInterface::*;
|
||||
if !self.globals_requested {
|
||||
self.globals_requested = true;
|
||||
self.mapper
|
||||
.add_synthetic_global(slf, ZxdgDecorationManagerV1, 1);
|
||||
}
|
||||
match interface {
|
||||
ZxdgDecorationManagerV1 | WpSecurityContextManagerV1 => {
|
||||
self.mapper.ignore_global(name);
|
||||
}
|
||||
_ => {
|
||||
self.mapper.forward_global(slf, name, interface, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_global_remove(&mut self, slf: &Rc<WlRegistry>, name: u32) {
|
||||
self.mapper.forward_global_remove(slf, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
57
src/xdg.rs
57
src/xdg.rs
|
|
@ -1,13 +1,20 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use wl_proxy::{
|
||||
object::ObjectUtils,
|
||||
object::{ObjectCoreApi, ObjectUtils},
|
||||
protocols::{
|
||||
wayland::{
|
||||
wl_buffer::WlBuffer,
|
||||
wl_output::{WlOutput, WlOutputTransform},
|
||||
wl_surface::{WlSurface, WlSurfaceHandler},
|
||||
},
|
||||
xdg_decoration_unstable_v1::{
|
||||
zxdg_decoration_manager_v1::{ZxdgDecorationManagerV1, ZxdgDecorationManagerV1Handler},
|
||||
zxdg_toplevel_decoration_v1::{
|
||||
ZxdgToplevelDecorationV1, ZxdgToplevelDecorationV1Handler,
|
||||
ZxdgToplevelDecorationV1Mode,
|
||||
},
|
||||
},
|
||||
xdg_shell::{
|
||||
xdg_popup::XdgPopup,
|
||||
xdg_positioner::{XdgPositioner, XdgPositionerHandler},
|
||||
|
|
@ -90,6 +97,54 @@ impl WlSurfaceHandler for ClientWlSurface {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ClientZxdgDecorationManagerV1;
|
||||
|
||||
impl ZxdgDecorationManagerV1Handler for ClientZxdgDecorationManagerV1 {
|
||||
fn handle_destroy(&mut self, slf: &Rc<ZxdgDecorationManagerV1>) {
|
||||
slf.delete_id();
|
||||
}
|
||||
|
||||
fn handle_get_toplevel_decoration(
|
||||
&mut self,
|
||||
_slf: &Rc<ZxdgDecorationManagerV1>,
|
||||
id: &Rc<ZxdgToplevelDecorationV1>,
|
||||
toplevel: &Rc<XdgToplevel>,
|
||||
) {
|
||||
id.set_handler(ClientZxdgToplevelDecorationV1 {
|
||||
toplevel: toplevel.clone(),
|
||||
});
|
||||
// TODO: send_configure here if a force mode is picked
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientZxdgToplevelDecorationV1 {
|
||||
toplevel: Rc<XdgToplevel>,
|
||||
}
|
||||
|
||||
impl ZxdgToplevelDecorationV1Handler for ClientZxdgToplevelDecorationV1 {
|
||||
fn handle_destroy(&mut self, slf: &Rc<ZxdgToplevelDecorationV1>) {
|
||||
slf.delete_id();
|
||||
}
|
||||
|
||||
fn handle_set_mode(
|
||||
&mut self,
|
||||
slf: &Rc<ZxdgToplevelDecorationV1>,
|
||||
mode: ZxdgToplevelDecorationV1Mode,
|
||||
) {
|
||||
let toplevel_handler = self.toplevel.get_handler_ref::<ClientXdgToplevel>();
|
||||
toplevel_handler
|
||||
.deco
|
||||
.set_prefers_ssd(mode == ZxdgToplevelDecorationV1Mode::SERVER_SIDE);
|
||||
slf.send_configure(mode);
|
||||
}
|
||||
|
||||
fn handle_unset_mode(&mut self, slf: &Rc<ZxdgToplevelDecorationV1>) {
|
||||
let toplevel_handler = self.toplevel.get_handler_ref::<ClientXdgToplevel>();
|
||||
toplevel_handler.deco.set_prefers_ssd(false);
|
||||
slf.send_configure(ZxdgToplevelDecorationV1Mode::CLIENT_SIDE);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientXdgWmBase {
|
||||
pub globals: Rc<Globals>,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue