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)]
|
#[derive(Default, Debug, Clone, PartialEq)]
|
||||||
struct DecoParams {
|
struct DecoParams {
|
||||||
has_geometry: bool,
|
has_geometry: bool,
|
||||||
|
prefers_ssd: bool,
|
||||||
is_active: bool,
|
is_active: bool,
|
||||||
bounds: Bounds,
|
bounds: Bounds,
|
||||||
restricted_edges: Edges<bool>,
|
restricted_edges: Edges<bool>,
|
||||||
|
|
@ -34,7 +35,6 @@ struct DecoParams {
|
||||||
pub struct Deco {
|
pub struct Deco {
|
||||||
last_params: RefCell<DecoParams>,
|
last_params: RefCell<DecoParams>,
|
||||||
next_params: RefCell<DecoParams>,
|
next_params: RefCell<DecoParams>,
|
||||||
top_size: i32,
|
|
||||||
border_size: i32,
|
border_size: i32,
|
||||||
|
|
||||||
wl_surface: Rc<WlSurface>,
|
wl_surface: Rc<WlSurface>,
|
||||||
|
|
@ -133,6 +133,15 @@ impl DecoSurface {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deco {
|
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(
|
pub fn new(
|
||||||
host_surface: &Rc<WlSurface>,
|
host_surface: &Rc<WlSurface>,
|
||||||
toplevel: &Rc<XdgToplevel>,
|
toplevel: &Rc<XdgToplevel>,
|
||||||
|
|
@ -151,7 +160,6 @@ impl Deco {
|
||||||
let deco = Rc::new(Deco {
|
let deco = Rc::new(Deco {
|
||||||
last_params: RefCell::new(Default::default()),
|
last_params: RefCell::new(Default::default()),
|
||||||
next_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,
|
border_size: args.thickness as i32,
|
||||||
wl_surface: wl_surface.clone(),
|
wl_surface: wl_surface.clone(),
|
||||||
subsurface,
|
subsurface,
|
||||||
|
|
@ -200,8 +208,8 @@ impl Deco {
|
||||||
height,
|
height,
|
||||||
};
|
};
|
||||||
let width = width + self.border_size * 2;
|
let width = width + self.border_size * 2;
|
||||||
let height = height + self.top_size + self.border_size;
|
let height = height + self.top_size() + self.border_size;
|
||||||
(x - self.border_size, y - self.top_size, width, height)
|
(x - self.border_size, y - self.top_size(), width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_restricted_edges(&self, edges: Edges<bool>) {
|
pub fn set_restricted_edges(&self, edges: Edges<bool>) {
|
||||||
|
|
@ -214,6 +222,11 @@ impl Deco {
|
||||||
params.is_active = is_active;
|
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<()> {
|
pub fn handle_commit(&self) -> eyre::Result<()> {
|
||||||
self.draw()
|
self.draw()
|
||||||
}
|
}
|
||||||
|
|
@ -221,19 +234,19 @@ impl Deco {
|
||||||
pub fn transform_configure(&self, width: i32, height: i32) -> (i32, i32) {
|
pub fn transform_configure(&self, width: i32, height: i32) -> (i32, i32) {
|
||||||
(
|
(
|
||||||
width - self.border_size * 2,
|
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) {
|
pub fn transform_size(&self, width: i32, height: i32) -> (i32, i32) {
|
||||||
(
|
(
|
||||||
width + self.border_size * 2,
|
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) {
|
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<()> {
|
fn draw(&self) -> eyre::Result<()> {
|
||||||
|
|
@ -273,13 +286,13 @@ impl Deco {
|
||||||
self.wl_surface.send_damage_buffer(0, 0, width, height);
|
self.wl_surface.send_damage_buffer(0, 0, width, height);
|
||||||
let input_region = self.globals.wl_compositor.new_send_create_region();
|
let input_region = self.globals.wl_compositor.new_send_create_region();
|
||||||
input_region.set_forward_to_client(false);
|
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(0, 0, self.border_size, height);
|
||||||
input_region.send_add(width - self.border_size, 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);
|
input_region.send_add(0, height - self.border_size, width, self.border_size);
|
||||||
self.wl_surface.send_set_input_region(Some(&input_region));
|
self.wl_surface.send_set_input_region(Some(&input_region));
|
||||||
self.subsurface
|
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();
|
self.wl_surface.send_commit();
|
||||||
// let _ = self.globals.wl_display.new_send_sync();
|
// let _ = self.globals.wl_display.new_send_sync();
|
||||||
Ok(())
|
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 clap::{CommandFactory, Parser};
|
||||||
use wl_proxy::{
|
use wl_proxy::{
|
||||||
baseline::Baseline,
|
baseline::Baseline,
|
||||||
|
global_mapper::GlobalMapper,
|
||||||
object::{ConcreteObject, Object, ObjectCoreApi, ObjectRcUtils},
|
object::{ConcreteObject, Object, ObjectCoreApi, ObjectRcUtils},
|
||||||
protocols::{
|
protocols::{
|
||||||
|
ObjectInterface,
|
||||||
linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
|
linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1,
|
||||||
wayland::{
|
wayland::{
|
||||||
wl_registry::{WlRegistry, WlRegistryHandler},
|
wl_registry::{WlRegistry, WlRegistryHandler},
|
||||||
wl_shm::WlShm,
|
wl_shm::WlShm,
|
||||||
},
|
},
|
||||||
|
xdg_decoration_unstable_v1::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1,
|
||||||
xdg_shell::xdg_wm_base::XdgWmBase,
|
xdg_shell::xdg_wm_base::XdgWmBase,
|
||||||
},
|
},
|
||||||
simple::{SimpleCommandExt, SimpleProxy},
|
simple::{SimpleCommandExt, SimpleProxy},
|
||||||
|
|
@ -27,12 +30,16 @@ mod xdg;
|
||||||
|
|
||||||
struct ClientWlRegistry {
|
struct ClientWlRegistry {
|
||||||
globals: Rc<Globals>,
|
globals: Rc<Globals>,
|
||||||
|
globals_requested: bool,
|
||||||
|
mapper: GlobalMapper,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientWlRegistry {
|
impl ClientWlRegistry {
|
||||||
fn new(globals: &Rc<Globals>) -> Self {
|
fn new(globals: &Rc<Globals>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
globals: globals.clone(),
|
globals: globals.clone(),
|
||||||
|
globals_requested: false,
|
||||||
|
mapper: GlobalMapper::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -45,6 +52,12 @@ impl WlRegistryHandler for ClientWlRegistry {
|
||||||
.set_handler(xdg::ClientXdgWmBase {
|
.set_handler(xdg::ClientXdgWmBase {
|
||||||
globals: self.globals.clone(),
|
globals: self.globals.clone(),
|
||||||
}),
|
}),
|
||||||
|
ZxdgDecorationManagerV1::INTERFACE => {
|
||||||
|
id.set_forward_to_server(false);
|
||||||
|
id.downcast::<ZxdgDecorationManagerV1>()
|
||||||
|
.set_handler(xdg::ClientZxdgDecorationManagerV1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
WlShm::INTERFACE => id
|
WlShm::INTERFACE => id
|
||||||
.downcast::<WlShm>()
|
.downcast::<WlShm>()
|
||||||
.set_handler(client_buffer::ClientWlShm),
|
.set_handler(client_buffer::ClientWlShm),
|
||||||
|
|
@ -53,7 +66,34 @@ impl WlRegistryHandler for ClientWlRegistry {
|
||||||
.set_handler(client_buffer::ClientZwpLinuxDmabufV1),
|
.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 std::rc::Rc;
|
||||||
|
|
||||||
use wl_proxy::{
|
use wl_proxy::{
|
||||||
object::ObjectUtils,
|
object::{ObjectCoreApi, ObjectUtils},
|
||||||
protocols::{
|
protocols::{
|
||||||
wayland::{
|
wayland::{
|
||||||
wl_buffer::WlBuffer,
|
wl_buffer::WlBuffer,
|
||||||
wl_output::{WlOutput, WlOutputTransform},
|
wl_output::{WlOutput, WlOutputTransform},
|
||||||
wl_surface::{WlSurface, WlSurfaceHandler},
|
wl_surface::{WlSurface, WlSurfaceHandler},
|
||||||
},
|
},
|
||||||
|
xdg_decoration_unstable_v1::{
|
||||||
|
zxdg_decoration_manager_v1::{ZxdgDecorationManagerV1, ZxdgDecorationManagerV1Handler},
|
||||||
|
zxdg_toplevel_decoration_v1::{
|
||||||
|
ZxdgToplevelDecorationV1, ZxdgToplevelDecorationV1Handler,
|
||||||
|
ZxdgToplevelDecorationV1Mode,
|
||||||
|
},
|
||||||
|
},
|
||||||
xdg_shell::{
|
xdg_shell::{
|
||||||
xdg_popup::XdgPopup,
|
xdg_popup::XdgPopup,
|
||||||
xdg_positioner::{XdgPositioner, XdgPositionerHandler},
|
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 struct ClientXdgWmBase {
|
||||||
pub globals: Rc<Globals>,
|
pub globals: Rc<Globals>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue