Set _NET_WM_WINDOW_TYPE and related fields properly (#176)
* add windowtype attribute to window tag. set _NET_WM_WINDOW_TYPE property for x11 * up * remove strum and strum_macros dependencies * Update configuration.md * Update window_definition.rs * Update window_definition.rs should work now Co-authored-by: Midnight Exigent <6959267-midnightexigent@users.noreply.gitlab.com>
This commit is contained in:
parent
1ed4925eb1
commit
31730bea32
6 changed files with 104 additions and 19 deletions
24
Cargo.lock
generated
24
Cargo.lock
generated
|
@ -389,6 +389,8 @@ dependencies = [
|
||||||
"simple-signal",
|
"simple-signal",
|
||||||
"smart-default",
|
"smart-default",
|
||||||
"structopt",
|
"structopt",
|
||||||
|
"strum 0.20.0",
|
||||||
|
"strum_macros 0.20.1",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
|
@ -1711,6 +1713,12 @@ version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
|
checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.20.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum_macros"
|
name = "strum_macros"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
|
@ -1723,6 +1731,18 @@ dependencies = [
|
||||||
"syn 1.0.72",
|
"syn 1.0.72",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.20.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote 1.0.9",
|
||||||
|
"syn 1.0.72",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "0.11.11"
|
version = "0.11.11"
|
||||||
|
@ -1778,8 +1798,8 @@ checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
"strum",
|
"strum 0.18.0",
|
||||||
"strum_macros",
|
"strum_macros 0.18.0",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"toml",
|
"toml",
|
||||||
"version-compare",
|
"version-compare",
|
||||||
|
|
|
@ -220,7 +220,7 @@ For Wayland users the `<reserve/>` block is replaced by the exclusive field in `
|
||||||
The previous `<window>` block would look like this.
|
The previous `<window>` block would look like this.
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<window name="main_window" stacking="fg" focusable="false" screen="1" exclusive="true">
|
<window name="main_window" stacking="fg" focusable="false" screen="1" exclusive="true" windowtype="normal">
|
||||||
<geometry anchor="top left" x="300px" y="50%" width="25%" height="20px"/>
|
<geometry anchor="top left" x="300px" y="50%" width="25%" height="20px"/>
|
||||||
<widget>
|
<widget>
|
||||||
<main/>
|
<main/>
|
||||||
|
@ -247,3 +247,10 @@ There are a couple things you can optionally configure on the window itself:
|
||||||
The details on how it is actually implemented are left to the compositor.
|
The details on how it is actually implemented are left to the compositor.
|
||||||
This option is only valid on Wayland.
|
This option is only valid on Wayland.
|
||||||
Possible values: `"true"`, `"false"`. Default: `"false"`
|
Possible values: `"true"`, `"false"`. Default: `"false"`
|
||||||
|
- `windowtype`: (X11 only) Can be used in determining the decoration, stacking position and other behavior of the window.
|
||||||
|
Possible values:
|
||||||
|
- `"normal"`: indicates that this is a normal, top-level window
|
||||||
|
- `"dock"`: indicates a dock or panel feature
|
||||||
|
- `"toolbar"`: toolbars "torn off" from the main application
|
||||||
|
- `"dialog"`: indicates that this is a dialog window
|
||||||
|
- Default: `"dock"` if reserve is set, else `"normal"`
|
||||||
|
|
|
@ -93,7 +93,7 @@ contain are defined. -->
|
||||||
|
|
||||||
<windows>
|
<windows>
|
||||||
<!-- These are the windows -->
|
<!-- These are the windows -->
|
||||||
<window name="bar" screen="0">
|
<window name="bar" screen="0" focusable="true" windowtype="dock">
|
||||||
<geometry x="0%" y="0%" width="100%" height="4%"/> <!--Specifies geometry-->
|
<geometry x="0%" y="0%" width="100%" height="4%"/> <!--Specifies geometry-->
|
||||||
<reserve side="top" distance="4%" layer="top"/>
|
<reserve side="top" distance="4%" layer="top"/>
|
||||||
<widget>
|
<widget>
|
||||||
|
|
|
@ -307,7 +307,6 @@ fn initialize_window(
|
||||||
window_def: config::EwwWindowDefinition,
|
window_def: config::EwwWindowDefinition,
|
||||||
) -> Result<EwwWindow> {
|
) -> Result<EwwWindow> {
|
||||||
let actual_window_rect = window_def.geometry.get_window_rectangle(monitor_geometry);
|
let actual_window_rect = window_def.geometry.get_window_rectangle(monitor_geometry);
|
||||||
|
|
||||||
if let Some(window) = display_backend::initialize_window(&window_def, monitor_geometry) {
|
if let Some(window) = display_backend::initialize_window(&window_def, monitor_geometry) {
|
||||||
window.set_title(&format!("Eww - {}", window_def.name));
|
window.set_title(&format!("Eww - {}", window_def.name));
|
||||||
let wm_class_name = format!("eww-{}", window_def.name);
|
let wm_class_name = format!("eww-{}", window_def.name);
|
||||||
|
@ -329,7 +328,7 @@ fn initialize_window(
|
||||||
gdk_window.set_override_redirect(!window_def.focusable);
|
gdk_window.set_override_redirect(!window_def.focusable);
|
||||||
|
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
display_backend::reserve_space_for(&window, monitor_geometry, window_def.struts)?;
|
display_backend::set_xprops(&window, monitor_geometry, &window_def)?;
|
||||||
|
|
||||||
// this should only be required on x11, as waylands layershell should manage the margins properly anways.
|
// this should only be required on x11, as waylands layershell should manage the margins properly anways.
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
|
@ -344,7 +343,6 @@ fn initialize_window(
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow!("monitor {} is unavailable", window_def.screen_number.unwrap()))
|
Err(anyhow!("monitor {} is unavailable", window_def.screen_number.unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply the provided window-positioning rules to the window.
|
/// Apply the provided window-positioning rules to the window.
|
||||||
|
|
|
@ -1,26 +1,55 @@
|
||||||
|
use super::*;
|
||||||
use crate::{ensure_xml_tag_is, value::NumWithUnit, widgets::widget_node};
|
use crate::{ensure_xml_tag_is, value::NumWithUnit, widgets::widget_node};
|
||||||
use anyhow::*;
|
|
||||||
use derive_more::*;
|
use derive_more::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use smart_default::SmartDefault;
|
use smart_default::SmartDefault;
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, str::FromStr};
|
||||||
|
|
||||||
use super::*;
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum EwwWindowType {
|
||||||
|
Dock,
|
||||||
|
Dialog,
|
||||||
|
Toolbar,
|
||||||
|
Normal,
|
||||||
|
}
|
||||||
|
impl FromStr for EwwWindowType {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"dock" => Ok(Self::Dock),
|
||||||
|
"toolbar" => Ok(Self::Toolbar),
|
||||||
|
"dialog" => Ok(Self::Dialog),
|
||||||
|
"normal" => Ok(Self::Normal),
|
||||||
|
x => Err(anyhow!("Unknown windowtype provided '{}'. Possible values are: dock, toolbar, dialog, normal", x)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EwwWindowType {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Full window-definition containing the fully expanded widget tree.
|
/// Full window-definition containing the fully expanded widget tree.
|
||||||
/// **Use this** rather than `[RawEwwWindowDefinition]`.
|
/// **Use this** rather than `[RawEwwWindowDefinition]`.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct EwwWindowDefinition {
|
pub struct EwwWindowDefinition {
|
||||||
pub name: WindowName,
|
pub name: WindowName,
|
||||||
|
|
||||||
pub geometry: EwwWindowGeometry,
|
pub geometry: EwwWindowGeometry,
|
||||||
pub stacking: WindowStacking,
|
pub stacking: WindowStacking,
|
||||||
pub screen_number: Option<i32>,
|
pub screen_number: Option<i32>,
|
||||||
pub widget: Box<dyn widget_node::WidgetNode>,
|
pub widget: Box<dyn widget_node::WidgetNode>,
|
||||||
pub focusable: bool,
|
pub focusable: bool,
|
||||||
|
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
|
pub window_type: EwwWindowType,
|
||||||
|
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
pub struts: StrutDefinition,
|
pub struts: StrutDefinition,
|
||||||
|
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub exclusive: bool,
|
pub exclusive: bool,
|
||||||
}
|
}
|
||||||
|
@ -35,6 +64,8 @@ impl EwwWindowDefinition {
|
||||||
widget: widget_node::generate_generic_widget_node(defs, &HashMap::new(), window.widget)?,
|
widget: widget_node::generate_generic_widget_node(defs, &HashMap::new(), window.widget)?,
|
||||||
focusable: window.focusable,
|
focusable: window.focusable,
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
|
window_type: window.window_type,
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
struts: window.struts,
|
struts: window.struts,
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
exclusive: window.exclusive,
|
exclusive: window.exclusive,
|
||||||
|
@ -52,6 +83,9 @@ pub struct RawEwwWindowDefinition {
|
||||||
pub widget: WidgetUse,
|
pub widget: WidgetUse,
|
||||||
pub focusable: bool,
|
pub focusable: bool,
|
||||||
|
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
|
pub window_type: EwwWindowType,
|
||||||
|
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
pub struts: StrutDefinition,
|
pub struts: StrutDefinition,
|
||||||
|
|
||||||
|
@ -78,6 +112,14 @@ impl RawEwwWindowDefinition {
|
||||||
Ok(node) => EwwWindowGeometry::from_xml_element(node)?,
|
Ok(node) => EwwWindowGeometry::from_xml_element(node)?,
|
||||||
Err(_) => EwwWindowGeometry::default(),
|
Err(_) => EwwWindowGeometry::default(),
|
||||||
},
|
},
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
|
window_type: match xml.attr("windowtype") {
|
||||||
|
Ok(v) => EwwWindowType::from_str(&v)?,
|
||||||
|
Err(_) => match struts {
|
||||||
|
Some(_) => EwwWindowType::Dock,
|
||||||
|
None => Default::default(),
|
||||||
|
},
|
||||||
|
},
|
||||||
widget: WidgetUse::from_xml_node(xml.child("widget")?.only_child()?)?,
|
widget: WidgetUse::from_xml_node(xml.child("widget")?.only_child()?)?,
|
||||||
stacking,
|
stacking,
|
||||||
screen_number,
|
screen_number,
|
||||||
|
|
|
@ -108,7 +108,7 @@ mod platform {
|
||||||
|
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
mod platform {
|
mod platform {
|
||||||
use crate::config::{EwwWindowDefinition, Side, StrutDefinition, WindowStacking};
|
use crate::config::{EwwWindowDefinition, EwwWindowType, Side, WindowStacking};
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
use gdkx11;
|
use gdkx11;
|
||||||
use gtk::{self, prelude::*};
|
use gtk::{self, prelude::*};
|
||||||
|
@ -139,9 +139,9 @@ mod platform {
|
||||||
Some(window)
|
Some(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve_space_for(window: >k::Window, monitor: gdk::Rectangle, strut_def: StrutDefinition) -> Result<()> {
|
pub fn set_xprops(window: >k::Window, monitor: gdk::Rectangle, window_def: &EwwWindowDefinition) -> Result<()> {
|
||||||
let backend = X11Backend::new()?;
|
let backend = X11Backend::new()?;
|
||||||
backend.reserve_space_for(window, monitor, strut_def)?;
|
backend.set_xprops_for(window, monitor, window_def)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +159,11 @@ mod platform {
|
||||||
Ok(X11Backend { conn, root_window: screen.root, atoms })
|
Ok(X11Backend { conn, root_window: screen.root, atoms })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reserve_space_for(
|
fn set_xprops_for(
|
||||||
&self,
|
&self,
|
||||||
window: >k::Window,
|
window: >k::Window,
|
||||||
monitor_rect: gdk::Rectangle,
|
monitor_rect: gdk::Rectangle,
|
||||||
strut_def: StrutDefinition,
|
window_def: &EwwWindowDefinition,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let win_id = window
|
let win_id = window
|
||||||
.get_window()
|
.get_window()
|
||||||
|
@ -172,6 +172,7 @@ mod platform {
|
||||||
.ok()
|
.ok()
|
||||||
.context("Failed to get x11 window for gtk window")?
|
.context("Failed to get x11 window for gtk window")?
|
||||||
.get_xid() as u32;
|
.get_xid() as u32;
|
||||||
|
let strut_def = window_def.struts;
|
||||||
let root_window_geometry = self.conn.get_geometry(self.root_window)?.reply()?;
|
let root_window_geometry = self.conn.get_geometry(self.root_window)?.reply()?;
|
||||||
|
|
||||||
let mon_end_x = (monitor_rect.x + monitor_rect.width) as u32 - 1u32;
|
let mon_end_x = (monitor_rect.x + monitor_rect.width) as u32 - 1u32;
|
||||||
|
@ -217,16 +218,33 @@ mod platform {
|
||||||
&strut_list,
|
&strut_list,
|
||||||
)?
|
)?
|
||||||
.check()?;
|
.check()?;
|
||||||
self.conn.flush()?;
|
|
||||||
Ok(())
|
x11rb::wrapper::ConnectionExt::change_property32(
|
||||||
|
&self.conn,
|
||||||
|
PropMode::REPLACE,
|
||||||
|
win_id,
|
||||||
|
self.atoms._NET_WM_WINDOW_TYPE,
|
||||||
|
self.atoms.ATOM,
|
||||||
|
&[match window_def.window_type {
|
||||||
|
EwwWindowType::Dock => self.atoms._NET_WM_WINDOW_TYPE_DOCK,
|
||||||
|
EwwWindowType::Normal => self.atoms._NET_WM_WINDOW_TYPE_NORMAL,
|
||||||
|
EwwWindowType::Dialog => self.atoms._NET_WM_WINDOW_TYPE_DIALOG,
|
||||||
|
EwwWindowType::Toolbar => self.atoms._NET_WM_WINDOW_TYPE_TOOLBAR,
|
||||||
|
}],
|
||||||
|
)?
|
||||||
|
.check()?;
|
||||||
|
|
||||||
|
self.conn.flush().context("Failed to send requests to X server")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x11rb::atom_manager! {
|
x11rb::atom_manager! {
|
||||||
pub AtomCollection: AtomCollectionCookie {
|
pub AtomCollection: AtomCollectionCookie {
|
||||||
_NET_WM_WINDOW_TYPE,
|
_NET_WM_WINDOW_TYPE,
|
||||||
|
_NET_WM_WINDOW_TYPE_NORMAL,
|
||||||
_NET_WM_WINDOW_TYPE_DOCK,
|
_NET_WM_WINDOW_TYPE_DOCK,
|
||||||
_NET_WM_WINDOW_TYPE_DIALOG,
|
_NET_WM_WINDOW_TYPE_DIALOG,
|
||||||
|
_NET_WM_WINDOW_TYPE_TOOLBAR,
|
||||||
_NET_WM_STATE,
|
_NET_WM_STATE,
|
||||||
_NET_WM_STATE_STICKY,
|
_NET_WM_STATE_STICKY,
|
||||||
_NET_WM_STATE_ABOVE,
|
_NET_WM_STATE_ABOVE,
|
||||||
|
|
Loading…
Add table
Reference in a new issue