* Initial commit for wayland support * Improvements to Wayland backend, structs and enums * gtk-layer-shell-rs imported * Eww compiles with wayland backend * Full layershell support * Compatibility with x11 backend * updated docs and better compatibily with X config * error in example * "screen" in config works * Updated documentation * bar example for wayland * eww follow focus when screen is undefined * NumWithUnit * Removed SurfaceDefinition for StrutDefinition again... * cargo fmt * fix match statement for screen number * fix focusable / kb interactivity * revision #2 * fix: compile error and example * feat: I fixed the deps X11 doesn't compile because of some x11 fuckery * fix: x11 fuckery PR NOW REEEEEEEEEEEEEEEEEEEEEEEEE * fix conflics and cargo fmt * i can't read * conflicts: a never ending loop... * dammit ptr * conflicts: Cargo.lock * Expression language (#124) * Add AST * add make-shift testing parser, and make stuff ocmpile * add proper expression parser * make string format use ' * Add empty doc page for expressions * add tests * Clean up file structure and add unary operators * Write documentation * make multiple daemons possible and make commands time out * Add EwwPaths struct and refactor path handling in general * Update docs to include <reserve> * Improve handling of paths and daemon-ids * Add elvis operator * Allow literal-tag content to use user-defined widgets * Add support for overriding monitor in CLI * change formatting config * Improve error messages for non-existant config dir * Added tooltips (#127) * update dependencies * Explicetely states where to look for installing eww (#131) I think this should be added, because we already had a couple of people opening issues because they didn't read the docs on how to install eww. * (Very) Rudimentry gif support (#143) * rudimentry gif support * revert main.rs * Fix variable reference detection, should fix #144 * cleanup TextPos in eww debug * Manually resolve escaped symbols in xml. This shouldn't be necesary. Fixes #154 and fixes #147 * Add JSON support for exprs (fixes #146) * Add docs for json values and make value related names shorter * Add animated icon * Initial commit for wayland support * Improvements to Wayland backend, structs and enums * gtk-layer-shell-rs imported * Eww compiles with wayland backend * Full layershell support * Compatibility with x11 backend * updated docs and better compatibily with X config * "screen" in config works * Updated documentation * eww follow focus when screen is undefined * Removed SurfaceDefinition for StrutDefinition again... * cargo fmt * fix match statement for screen number * fix focusable / kb interactivity * revision #2 * fix: compile error and example * feat: I fixed the deps X11 doesn't compile because of some x11 fuckery * fix conflics and cargo fmt * i can't read * conflicts: a never ending loop... * dammit ptr * conflicts: Cargo.lock * yeeting git syntax * trying to resolve conflicts * yeeting Cargo.lock... * i try * revision: removing duplicates * fix geometry, example and improving docs * clearing up the documentation * I forgot the scss file. I also edited the bar to take advantage of eww expressions. * more yeeting and moved exclusive to window Co-authored-by: Bryan Ndjeutcha <ndjeutcha@gmail.com> Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com> Co-authored-by: undefinedDarkness <38278035+undefinedDarkness@users.noreply.github.com> Co-authored-by: legendofmiracles <30902201+legendofmiracles@users.noreply.github.com>
230 lines
9.8 KiB
Rust
230 lines
9.8 KiB
Rust
pub use platform::*;
|
|
|
|
#[cfg(feature = "no-x11-wayland")]
|
|
mod platform {
|
|
use crate::config::{Side, StrutDefinition};
|
|
use anyhow::*;
|
|
pub fn reserve_space_for(window: >k::Window, monitor: gdk::Rectangle, strut_def: StrutDefinition) -> Result<()> {
|
|
Err(anyhow!("Cannot reserve space on non X11 or and wayland backends"))
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "wayland")]
|
|
mod platform {
|
|
use gdk;
|
|
use crate::{
|
|
config::{EwwWindowDefinition, AnchorAlignment, Side, WindowStacking},
|
|
};
|
|
use anyhow::*;
|
|
use gtk::prelude::*;
|
|
|
|
pub fn initialize_window(window_def: &mut EwwWindowDefinition, monitor: gdk::Rectangle) -> gtk::Window {
|
|
let window = gtk::Window::new(gtk::WindowType::Toplevel);
|
|
// Initialising a layer shell surface
|
|
gtk_layer_shell::init_for_window(&window);
|
|
// Sets the monitor where the surface is shown
|
|
match window_def.screen_number {
|
|
Some(index) => {
|
|
if let Some(monitor) = gdk::Display::get_default()
|
|
.expect("could not get default display")
|
|
.get_monitor(index) {
|
|
gtk_layer_shell::set_monitor(&window, &monitor);
|
|
};
|
|
}
|
|
None => {}
|
|
};
|
|
window.set_resizable(true);
|
|
|
|
// Sets the layer where the layer shell surface will spawn
|
|
match window_def.stacking {
|
|
WindowStacking::Foreground => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Top),
|
|
WindowStacking::Background => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Background),
|
|
WindowStacking::Bottom => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Bottom),
|
|
WindowStacking::Overlay => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Overlay),
|
|
}
|
|
|
|
// Sets the keyboard interactivity
|
|
gtk_layer_shell::set_keyboard_interactivity(&window, window_def.focusable);
|
|
// Positioning surface
|
|
let mut top = false;
|
|
let mut left = false;
|
|
let mut right = false;
|
|
let mut bottom = false;
|
|
|
|
match window_def.geometry.anchor_point.x {
|
|
AnchorAlignment::START => left = true,
|
|
AnchorAlignment::CENTER => {}
|
|
AnchorAlignment::END => right = true,
|
|
}
|
|
match window_def.geometry.anchor_point.y {
|
|
AnchorAlignment::START => top = true,
|
|
AnchorAlignment::CENTER => {}
|
|
AnchorAlignment::END => bottom = true,
|
|
}
|
|
|
|
gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Left, left);
|
|
gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Right, right);
|
|
gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Top, top);
|
|
gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Bottom, bottom);
|
|
|
|
let xoffset = window_def.geometry.offset.x.relative_to(monitor.width);
|
|
let yoffset = window_def.geometry.offset.y.relative_to(monitor.height);
|
|
|
|
if left {
|
|
gtk_layer_shell::set_margin(&window, gtk_layer_shell::Edge::Left, xoffset);
|
|
} else {
|
|
gtk_layer_shell::set_margin(&window, gtk_layer_shell::Edge::Right, xoffset);
|
|
}
|
|
if bottom {
|
|
gtk_layer_shell::set_margin(&window, gtk_layer_shell::Edge::Bottom, yoffset);
|
|
} else {
|
|
gtk_layer_shell::set_margin(&window, gtk_layer_shell::Edge::Top, yoffset);
|
|
}
|
|
|
|
if window_def.exclusive {
|
|
gtk_layer_shell::auto_exclusive_zone_enable(&window);
|
|
}
|
|
window
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "x11")]
|
|
mod platform {
|
|
use crate::config::{EwwWindowDefinition, Side, StrutDefinition, WindowStacking};
|
|
use anyhow::*;
|
|
use gdkx11;
|
|
use gtk::{self, prelude::*};
|
|
use x11rb::protocol::xproto::ConnectionExt;
|
|
|
|
use x11rb::{
|
|
self,
|
|
connection::Connection,
|
|
protocol::xproto::*,
|
|
rust_connection::{DefaultStream, RustConnection},
|
|
};
|
|
|
|
pub fn initialize_window(window_def: &mut EwwWindowDefinition, _monitor: gdk::Rectangle) -> gtk::Window {
|
|
let window = if window_def.focusable {
|
|
gtk::Window::new(gtk::WindowType::Toplevel)
|
|
} else {
|
|
gtk::Window::new(gtk::WindowType::Popup)
|
|
};
|
|
window.set_resizable(true);
|
|
if !window_def.focusable {
|
|
window.set_type_hint(gdk::WindowTypeHint::Dock);
|
|
}
|
|
if window_def.stacking == WindowStacking::Foreground {
|
|
window.set_keep_above(true);
|
|
} else {
|
|
window.set_keep_below(true);
|
|
}
|
|
window
|
|
}
|
|
|
|
pub fn reserve_space_for(window: >k::Window, monitor: gdk::Rectangle, strut_def: StrutDefinition) -> Result<()> {
|
|
let backend = X11Backend::new()?;
|
|
backend.reserve_space_for(window, monitor, strut_def)?;
|
|
Ok(())
|
|
}
|
|
|
|
struct X11Backend {
|
|
conn: RustConnection<DefaultStream>,
|
|
root_window: u32,
|
|
atoms: AtomCollection,
|
|
}
|
|
|
|
impl X11Backend {
|
|
fn new() -> Result<Self> {
|
|
let (conn, screen_num) = RustConnection::connect(None)?;
|
|
let screen = conn.setup().roots[screen_num].clone();
|
|
let atoms = AtomCollection::new(&conn)?.reply()?;
|
|
Ok(X11Backend { conn, root_window: screen.root, atoms })
|
|
}
|
|
|
|
fn reserve_space_for(
|
|
&self,
|
|
window: >k::Window,
|
|
monitor_rect: gdk::Rectangle,
|
|
strut_def: StrutDefinition,
|
|
) -> Result<()> {
|
|
let win_id = window
|
|
.get_window()
|
|
.context("Couldn't get gdk window from gtk window")?
|
|
.downcast::<gdkx11::X11Window>()
|
|
.ok()
|
|
.context("Failed to get x11 window for gtk window")?
|
|
.get_xid() as u32;
|
|
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_y = (monitor_rect.y + monitor_rect.height) as u32 - 1u32;
|
|
|
|
let dist = match strut_def.side {
|
|
Side::Left | Side::Right => strut_def.dist.relative_to(monitor_rect.width) as u32,
|
|
Side::Top | Side::Bottom => strut_def.dist.relative_to(monitor_rect.height) as u32,
|
|
_ => (monitor_rect.height / 2) as u32,
|
|
};
|
|
|
|
// don't question it,.....
|
|
// it's how the X gods want it to be.
|
|
// left, right, top, bottom, left_start_y, left_end_y, right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x, bottom_end_x
|
|
#[rustfmt::skip]
|
|
let strut_list: Vec<u8> = match strut_def.side {
|
|
Side::Left => vec![dist + monitor_rect.x as u32, 0, 0, 0, monitor_rect.y as u32, mon_end_y, 0, 0, 0, 0, 0, 0],
|
|
Side::Right => vec![0, root_window_geometry.width as u32 - mon_end_x + dist, 0, 0, 0, 0, monitor_rect.y as u32, mon_end_y, 0, 0, 0, 0],
|
|
Side::Top => vec![0, 0, dist + monitor_rect.y as u32, 0, 0, 0, 0, 0, monitor_rect.x as u32, mon_end_x, 0, 0],
|
|
Side::Bottom => vec![0, 0, 0, root_window_geometry.height as u32 - mon_end_y + dist, 0, 0, 0, 0, 0, 0, monitor_rect.x as u32, mon_end_x],
|
|
// This should never happen but if it does the window will be anchored on the
|
|
// right of the screen
|
|
_ => vec![0, root_window_geometry.width as u32 - mon_end_x + dist, 0, 0, 0, 0, monitor_rect.y as u32, mon_end_y, 0, 0, 0, 0],
|
|
}.iter().flat_map(|x| x.to_le_bytes().to_vec()).collect();
|
|
|
|
self.conn
|
|
.change_property(
|
|
PropMode::REPLACE,
|
|
win_id,
|
|
self.atoms._NET_WM_STRUT,
|
|
self.atoms.CARDINAL,
|
|
32,
|
|
4,
|
|
&strut_list[0..16],
|
|
)?
|
|
.check()?;
|
|
self.conn
|
|
.change_property(
|
|
PropMode::REPLACE,
|
|
win_id,
|
|
self.atoms._NET_WM_STRUT_PARTIAL,
|
|
self.atoms.CARDINAL,
|
|
32,
|
|
12,
|
|
&strut_list,
|
|
)?
|
|
.check()?;
|
|
self.conn.flush()?;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
x11rb::atom_manager! {
|
|
pub AtomCollection: AtomCollectionCookie {
|
|
_NET_WM_WINDOW_TYPE,
|
|
_NET_WM_WINDOW_TYPE_DOCK,
|
|
_NET_WM_WINDOW_TYPE_DIALOG,
|
|
_NET_WM_STATE,
|
|
_NET_WM_STATE_STICKY,
|
|
_NET_WM_STATE_ABOVE,
|
|
_NET_WM_STATE_BELOW,
|
|
_NET_WM_NAME,
|
|
_NET_WM_STRUT,
|
|
_NET_WM_STRUT_PARTIAL,
|
|
WM_NAME,
|
|
UTF8_STRING,
|
|
COMPOUND_TEXT,
|
|
CARDINAL,
|
|
ATOM,
|
|
WM_CLASS,
|
|
STRING,
|
|
}
|
|
}
|
|
}
|