Add stacking option to window definition
This commit is contained in:
parent
3d5509b570
commit
0fca322bde
4 changed files with 106 additions and 12 deletions
29
src/app.rs
29
src/app.rs
|
@ -1,4 +1,5 @@
|
|||
use crate::*;
|
||||
use config::WindowStacking;
|
||||
use debug_stub_derive::*;
|
||||
use script_var_handler::*;
|
||||
use std::collections::HashMap;
|
||||
|
@ -27,7 +28,7 @@ impl App {
|
|||
pub fn handle_user_command(&mut self, opts: &Opt) -> Result<()> {
|
||||
match &opts.action {
|
||||
OptAction::Update { fieldname, value } => self.update_state(fieldname.clone(), value.clone())?,
|
||||
OptAction::OpenWindow { window_name } => self.open_window(&window_name)?,
|
||||
OptAction::OpenWindow { window_name, pos, size } => self.open_window(&window_name, *pos, *size)?,
|
||||
OptAction::CloseWindow { window_name } => self.close_window(&window_name)?,
|
||||
OptAction::KillServer => {
|
||||
log::info!("Received kill command, stopping server!");
|
||||
|
@ -68,14 +69,22 @@ impl App {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn open_window(&mut self, window_name: &config::WindowName) -> Result<()> {
|
||||
let window_def = self
|
||||
fn open_window(
|
||||
&mut self,
|
||||
window_name: &config::WindowName,
|
||||
pos: Option<util::Coords>,
|
||||
size: Option<util::Coords>,
|
||||
) -> Result<()> {
|
||||
let mut window_def = self
|
||||
.eww_config
|
||||
.get_windows()
|
||||
.get(window_name)
|
||||
.context(format!("No window named '{}' defined", window_name))?
|
||||
.clone();
|
||||
|
||||
window_def.position = pos.unwrap_or_else(|| window_def.position);
|
||||
window_def.size = size.unwrap_or_else(|| window_def.size);
|
||||
|
||||
let window = gtk::Window::new(gtk::WindowType::Popup);
|
||||
window.set_title("Eww");
|
||||
window.set_wmclass("noswallow", "noswallow");
|
||||
|
@ -107,8 +116,14 @@ impl App {
|
|||
gdk_window.set_override_redirect(true);
|
||||
gdk_window.move_(window_def.position.0, window_def.position.1);
|
||||
gdk_window.show();
|
||||
gdk_window.raise();
|
||||
window.set_keep_above(true);
|
||||
|
||||
if window_def.stacking == WindowStacking::Foreground {
|
||||
gdk_window.raise();
|
||||
window.set_keep_above(true);
|
||||
} else {
|
||||
gdk_window.lower();
|
||||
window.set_keep_below(true);
|
||||
}
|
||||
|
||||
self.windows.insert(window_name.clone(), window);
|
||||
|
||||
|
@ -126,8 +141,10 @@ impl App {
|
|||
|
||||
let windows = self.windows.clone();
|
||||
for (window_name, window) in windows {
|
||||
let old_pos = window.get_position();
|
||||
let old_size = window.get_size();
|
||||
window.close();
|
||||
self.open_window(&window_name)?;
|
||||
self.open_window(&window_name, Some(old_pos.into()), Some(old_size.into()))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -2,10 +2,12 @@ use crate::util;
|
|||
use crate::value::PrimitiveValue;
|
||||
use crate::value::VarName;
|
||||
use anyhow::*;
|
||||
use derive_more;
|
||||
use element::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use util::Coords;
|
||||
use xml_ext::*;
|
||||
|
||||
pub mod element;
|
||||
|
@ -163,8 +165,9 @@ impl fmt::Display for WindowName {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct EwwWindowDefinition {
|
||||
pub position: (i32, i32),
|
||||
pub size: (i32, i32),
|
||||
pub position: Coords,
|
||||
pub size: Coords,
|
||||
pub stacking: WindowStacking,
|
||||
pub widget: WidgetUse,
|
||||
}
|
||||
|
||||
|
@ -173,11 +176,50 @@ impl EwwWindowDefinition {
|
|||
ensure_xml_tag_is!(xml, "window");
|
||||
|
||||
let size_node = xml.child("size")?;
|
||||
let size = (size_node.attr("x")?.parse()?, size_node.attr("y")?.parse()?);
|
||||
let size = Coords(size_node.attr("x")?.parse()?, size_node.attr("y")?.parse()?);
|
||||
let pos_node = xml.child("pos")?;
|
||||
let position = (pos_node.attr("x")?.parse()?, pos_node.attr("y")?.parse()?);
|
||||
let position = Coords(pos_node.attr("x")?.parse()?, pos_node.attr("y")?.parse()?);
|
||||
|
||||
let stacking = xml
|
||||
.attr("stacking")
|
||||
.ok()
|
||||
.map(|stacking| stacking.parse::<WindowStacking>())
|
||||
.transpose()?
|
||||
.unwrap_or_else(WindowStacking::default);
|
||||
|
||||
let widget = WidgetUse::from_xml_node(xml.child("widget")?.only_child()?)?;
|
||||
Ok(EwwWindowDefinition { position, size, widget })
|
||||
Ok(EwwWindowDefinition {
|
||||
position,
|
||||
size,
|
||||
widget,
|
||||
stacking,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display)]
|
||||
pub enum WindowStacking {
|
||||
Foreground,
|
||||
Background,
|
||||
}
|
||||
|
||||
impl Default for WindowStacking {
|
||||
fn default() -> Self {
|
||||
WindowStacking::Foreground
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for WindowStacking {
|
||||
type Err = anyhow::Error;
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"foreground" | "fg" | "f" => Ok(WindowStacking::Foreground),
|
||||
"background" | "bg" | "b" => Ok(WindowStacking::Background),
|
||||
_ => Err(anyhow!(
|
||||
"Couldn't parse '{}' as window stacking, must be either foreground, fg, background or bg",
|
||||
s
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -2,6 +2,8 @@
|
|||
#![feature(result_cloned)]
|
||||
#![feature(iterator_fold_self)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(str_split_once)]
|
||||
|
||||
extern crate gio;
|
||||
extern crate gtk;
|
||||
|
||||
|
@ -70,7 +72,15 @@ pub enum OptAction {
|
|||
Update { fieldname: VarName, value: PrimitiveValue },
|
||||
|
||||
#[structopt(name = "open")]
|
||||
OpenWindow { window_name: config::WindowName },
|
||||
OpenWindow {
|
||||
window_name: config::WindowName,
|
||||
|
||||
#[structopt(short, long)]
|
||||
pos: Option<util::Coords>,
|
||||
|
||||
#[structopt(short, long)]
|
||||
size: Option<util::Coords>,
|
||||
},
|
||||
|
||||
#[structopt(name = "close")]
|
||||
CloseWindow { window_name: config::WindowName },
|
||||
|
|
25
src/util.rs
25
src/util.rs
|
@ -2,6 +2,8 @@ use anyhow::*;
|
|||
use extend::ext;
|
||||
use grass;
|
||||
use itertools::Itertools;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn parse_scss_from_file<P: AsRef<Path>>(path: P) -> Result<String> {
|
||||
|
@ -37,3 +39,26 @@ pub fn parse_duration(s: &str) -> Result<std::time::Duration> {
|
|||
Err(anyhow!("unrecognized time format: {}", s))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct Coords(pub i32, pub i32);
|
||||
|
||||
impl fmt::Display for Coords {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}x{}", self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Coords {
|
||||
type Err = anyhow::Error;
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
let (x, y) = s.split_once('x').ok_or_else(|| anyhow!("must be formatted like 200x500"))?;
|
||||
Ok(Coords(x.parse()?, y.parse()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(i32, i32)> for Coords {
|
||||
fn from((x, y): (i32, i32)) -> Self {
|
||||
Coords(x, y)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue