Add ICCCM WM_NORMAL_HINTS
This commit is contained in:
parent
692e55c246
commit
bb00bad0e4
5 changed files with 281 additions and 12 deletions
|
@ -13,6 +13,7 @@ homepage = "https://git.friedl.net/incubator/xcb-wm"
|
|||
[dependencies]
|
||||
xcb = "1"
|
||||
paste = "1"
|
||||
bitflags = "1.3.2"
|
||||
|
||||
[features]
|
||||
icccm = []
|
||||
|
|
|
@ -112,17 +112,6 @@ mod tests {
|
|||
println!("{:?}", reply);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_number_of_desktops() {
|
||||
let xcb_con = xcb::Connection::connect(Option::None).unwrap().0;
|
||||
let ewmh_con = crate::ewmh::Connection::connect(&xcb_con);
|
||||
|
||||
let request = crate::ewmh::proto::SetNumberOfDesktops::new(&ewmh_con, 4);
|
||||
let cookie = ewmh_con.send_request_checked(&request);
|
||||
let reply = xcb_con.check_request(cookie);
|
||||
println!("{:?}", reply);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn number_of_desktops2() {
|
||||
// let xcb_con = xcb::Connection::connect(Option::None).unwrap().0;
|
||||
|
|
|
@ -76,7 +76,7 @@ impl<'a> Connection<'a> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::icccm::proto::SetWmName;
|
||||
use crate::icccm::proto::{GetWmNormalHints, SetWmName, SetWmNormalHints, WmSizeHints};
|
||||
|
||||
#[test]
|
||||
fn number_of_desktops() {
|
||||
|
@ -108,4 +108,19 @@ mod tests {
|
|||
let reply = xcb_con.check_request(cookie);
|
||||
println!("{:?}", reply);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_wm_normal_hints() {
|
||||
let xcb_con = xcb::Connection::connect(Option::None).unwrap().0;
|
||||
let icccm_con = crate::icccm::Connection::connect(&xcb_con);
|
||||
|
||||
use xcb::XidNew;
|
||||
|
||||
let window = unsafe { xcb::x::Window::new(0x440013e) };
|
||||
|
||||
let request = GetWmNormalHints::new(window);
|
||||
let cookie = icccm_con.send_request(&request);
|
||||
let reply = icccm_con.wait_for_reply(cookie);
|
||||
println!("{:?}", reply);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use bitflags::bitflags;
|
||||
use std::convert::TryInto;
|
||||
use xcb::{Xid, XidNew};
|
||||
|
||||
use crate::icccm::traits::*;
|
||||
|
@ -257,3 +259,225 @@ icccm_set_property! {
|
|||
}
|
||||
}
|
||||
// }}}
|
||||
|
||||
// WM_NORMAL_HINTS,
|
||||
// {{{
|
||||
|
||||
bitflags! {
|
||||
struct WmSizeHintsFlags: u32 {
|
||||
const Empty = 0b0000_0000_0000;
|
||||
const USPosition = 0b0000_0000_0001;
|
||||
const USSize = 0b0000_0000_0010;
|
||||
const PPosition = 0b0000_0000_0100;
|
||||
const PSize = 0b0000_0000_1000;
|
||||
const PMinSize = 0b0000_0001_0000;
|
||||
const PMaxSize = 0b0000_0010_0000;
|
||||
const PResizeInc = 0b0000_0100_0000;
|
||||
const PAspect = 0b0000_1000_0000;
|
||||
const PBaseSize = 0b0001_0000_0000;
|
||||
const PWinGravity = 0b0010_0000_0000;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WmSizeHints {
|
||||
flags: WmSizeHintsFlags,
|
||||
x: u32,
|
||||
y: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
min_width: u32,
|
||||
min_height: u32,
|
||||
max_width: u32,
|
||||
max_height: u32,
|
||||
width_inc: u32,
|
||||
height_inc: u32,
|
||||
min_aspect: (u32, u32),
|
||||
max_aspect: (u32, u32),
|
||||
base_width: u32,
|
||||
base_height: u32,
|
||||
win_gravity: xcb::x::Gravity,
|
||||
}
|
||||
|
||||
impl Default for WmSizeHints {
|
||||
fn default() -> Self {
|
||||
WmSizeHints {
|
||||
flags: WmSizeHintsFlags::Empty,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
min_width: 0,
|
||||
min_height: 0,
|
||||
max_width: 0,
|
||||
max_height: 0,
|
||||
width_inc: 0,
|
||||
height_inc: 0,
|
||||
min_aspect: (0, 0),
|
||||
max_aspect: (0, 0),
|
||||
base_width: 0,
|
||||
base_height: 0,
|
||||
win_gravity: xcb::x::Gravity::NorthWest,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WmSizeHints {
|
||||
pub fn as_data(&mut self) -> Vec<u32> {
|
||||
vec![
|
||||
self.flags.bits,
|
||||
self.x,
|
||||
self.y,
|
||||
self.width,
|
||||
self.height,
|
||||
self.min_width,
|
||||
self.min_height,
|
||||
self.max_width,
|
||||
self.max_height,
|
||||
self.width_inc,
|
||||
self.height_inc,
|
||||
self.min_aspect.0,
|
||||
self.min_aspect.1,
|
||||
self.max_aspect.0,
|
||||
self.max_aspect.1,
|
||||
self.base_width,
|
||||
self.base_height,
|
||||
self.win_gravity as u32,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn from_reply(reply: xcb::x::GetPropertyReply) -> WmSizeHints {
|
||||
let packed_vals = reply.value::<u32>();
|
||||
WmSizeHints {
|
||||
flags: WmSizeHintsFlags::from_bits_truncate(packed_vals[0]),
|
||||
x: packed_vals[1],
|
||||
y: packed_vals[2],
|
||||
width: packed_vals[3],
|
||||
height: packed_vals[4],
|
||||
min_width: packed_vals[5],
|
||||
min_height: packed_vals[6],
|
||||
max_width: packed_vals[7],
|
||||
max_height: packed_vals[8],
|
||||
width_inc: packed_vals[9],
|
||||
height_inc: packed_vals[10],
|
||||
min_aspect: (packed_vals[11], packed_vals[12]),
|
||||
max_aspect: (packed_vals[13], packed_vals[14]),
|
||||
base_width: packed_vals[15],
|
||||
base_height: packed_vals[16],
|
||||
win_gravity: unsafe { std::mem::transmute(packed_vals[17]) },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn position(&mut self, user_specified: bool, x: u32, y: u32) {
|
||||
// reset
|
||||
self.flags &= !(WmSizeHintsFlags::USPosition | WmSizeHintsFlags::PPosition);
|
||||
|
||||
if user_specified {
|
||||
self.flags |= WmSizeHintsFlags::USPosition
|
||||
} else {
|
||||
self.flags |= WmSizeHintsFlags::PPosition
|
||||
}
|
||||
|
||||
self.x = x;
|
||||
self.y = y;
|
||||
}
|
||||
|
||||
pub fn size(&mut self, user_specified: bool, width: u32, height: u32) {
|
||||
// reset
|
||||
self.flags &= !(WmSizeHintsFlags::USSize | WmSizeHintsFlags::PSize);
|
||||
|
||||
if user_specified {
|
||||
self.flags |= WmSizeHintsFlags::USSize
|
||||
} else {
|
||||
self.flags |= WmSizeHintsFlags::PSize
|
||||
}
|
||||
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
}
|
||||
|
||||
pub fn min_size(&mut self, min_width: u32, min_height: u32) {
|
||||
self.flags |= WmSizeHintsFlags::PMinSize;
|
||||
|
||||
self.min_width = min_width;
|
||||
self.min_height = min_height;
|
||||
}
|
||||
|
||||
pub fn max_size(&mut self, max_width: u32, max_height: u32) {
|
||||
self.flags |= WmSizeHintsFlags::PMaxSize;
|
||||
|
||||
self.max_width = max_width;
|
||||
self.max_height = max_height;
|
||||
}
|
||||
|
||||
pub fn resize_inc(&mut self, width_inc: u32, height_inc: u32) {
|
||||
self.flags |= WmSizeHintsFlags::PResizeInc;
|
||||
|
||||
self.width_inc = width_inc;
|
||||
self.height_inc = height_inc;
|
||||
}
|
||||
|
||||
pub fn aspect(&mut self, min_aspect: (u32, u32), max_aspect: (u32, u32)) {
|
||||
self.flags |= WmSizeHintsFlags::PAspect;
|
||||
|
||||
self.min_aspect = min_aspect;
|
||||
self.max_aspect = max_aspect;
|
||||
}
|
||||
|
||||
pub fn base_size(&mut self, base_width: u32, base_height: u32) {
|
||||
self.flags |= WmSizeHintsFlags::PBaseSize;
|
||||
|
||||
self.base_width = base_width;
|
||||
self.base_height = base_height;
|
||||
}
|
||||
|
||||
pub fn win_gravity(&mut self, win_gravity: xcb::x::Gravity) {
|
||||
self.flags |= WmSizeHintsFlags::PWinGravity;
|
||||
|
||||
self.win_gravity = win_gravity;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GetWmNormalHintsReply {
|
||||
pub size_hints: WmSizeHints,
|
||||
}
|
||||
|
||||
impl From<xcb::x::GetPropertyReply> for GetWmNormalHintsReply {
|
||||
fn from(reply: xcb::x::GetPropertyReply) -> Self {
|
||||
GetWmNormalHintsReply {
|
||||
size_hints: WmSizeHints::from_reply(reply),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
icccm_get_property! {
|
||||
request=GetWmNormalHints{
|
||||
window: client,
|
||||
property: ATOM_WM_NORMAL_HINTS,
|
||||
xtype: ATOM_WM_SIZE_HINTS
|
||||
},
|
||||
reply=GetWmNormalHintsReply
|
||||
}
|
||||
|
||||
pub struct SetWmNormalHints {
|
||||
window: xcb::x::Window,
|
||||
data: Vec<u32>,
|
||||
}
|
||||
|
||||
impl SetWmNormalHints {
|
||||
pub fn new(window: xcb::x::Window, size_hints: &mut WmSizeHints) -> SetWmNormalHints {
|
||||
SetWmNormalHints {
|
||||
window: window,
|
||||
data: size_hints.as_data(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
icccm_set_hint_property! {
|
||||
request=SetWmNormalHints{
|
||||
property: ATOM_WM_NORMAL_HINTS,
|
||||
xtype: ATOM_WM_SIZE_HINTS
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
|
|
|
@ -126,3 +126,43 @@ macro_rules! icccm_set_property {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! icccm_set_hint_property {
|
||||
(request=$request:ident{
|
||||
property: $property:ident,
|
||||
xtype: $type:ident
|
||||
}) => {
|
||||
impl<'a> IcccmRequest<'a> for $request {
|
||||
type XcbRequest = xcb::x::ChangeProperty<'a, u32>;
|
||||
type IcccmCookie = xcb::VoidCookie;
|
||||
|
||||
fn xcb_request(&'a self, con: &Connection) -> xcb::x::ChangeProperty<'a, u32> {
|
||||
xcb::x::ChangeProperty {
|
||||
mode: xcb::x::PropMode::Replace,
|
||||
window: self.window,
|
||||
property: xcb::x::$property,
|
||||
r#type: xcb::x::$type,
|
||||
data: &self.data,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_cookie(&'a self, xcb_cookie: xcb::VoidCookie) -> Self::IcccmCookie {
|
||||
xcb_cookie
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IcccmVoidRequestChecked<'a> for $request {
|
||||
type XcbRequest = xcb::x::ChangeProperty<'a, u32>;
|
||||
|
||||
fn xcb_request(&'a self, con: &Connection) -> xcb::x::ChangeProperty<'a, u32> {
|
||||
xcb::x::ChangeProperty {
|
||||
mode: xcb::x::PropMode::Replace,
|
||||
window: self.window,
|
||||
property: xcb::x::$property,
|
||||
r#type: xcb::x::$type,
|
||||
data: &self.data,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue