Implement selectable windows, fixes #27

This commit is contained in:
elkowar 2020-10-23 19:40:39 +02:00
parent 4bbbfe7eab
commit a906c18bd7
4 changed files with 39 additions and 20 deletions

View file

@ -4,14 +4,13 @@ use crate::{
eww_state,
script_var_handler::*,
util,
value::{Coords, NumWithUnit, PrimitiveValue, VarName},
value::{AttrValue, Coords, NumWithUnit, PrimitiveValue, VarName},
widgets,
};
use anyhow::*;
use crossbeam_channel;
use debug_stub_derive::*;
use gdk::WindowExt;
use glib::Cast;
use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt};
use itertools::Itertools;
@ -109,7 +108,7 @@ impl App {
.eww_config
.get_windows()
.get(window_name)
.context(format!("No window named '{}' defined", window_name))?
.with_context(|| format!("No window named '{}' defined", window_name))?
.clone();
let display = gdk::Display::get_default().expect("could not get default display");
@ -119,16 +118,23 @@ impl App {
let monitor_geometry = display.get_default_screen().get_monitor_geometry(*screen_number);
window_def.position = pos.unwrap_or_else(|| window_def.position);
window_def.size = size.unwrap_or_else(|| window_def.size);
window_def.position = pos.unwrap_or(window_def.position);
window_def.size = size.unwrap_or(window_def.size);
let actual_window_rect = get_window_rectangle_in_screen(monitor_geometry, window_def.position, window_def.size);
let window = gtk::Window::new(gtk::WindowType::Popup);
let window = if window_def.focusable {
gtk::Window::new(gtk::WindowType::Toplevel)
} else {
gtk::Window::new(gtk::WindowType::Popup)
};
window.set_title(&format!("Eww - {}", window_name));
let wm_class_name = format!("eww-{}", window_name);
window.set_wmclass(&wm_class_name, &wm_class_name);
window.set_type_hint(gdk::WindowTypeHint::Dock);
if !window_def.focusable {
window.set_type_hint(gdk::WindowTypeHint::Dock);
}
window.set_position(gtk::WindowPosition::Center);
window.set_default_size(actual_window_rect.width, actual_window_rect.height);
window.set_size_request(actual_window_rect.width, actual_window_rect.height);
@ -138,16 +144,12 @@ impl App {
// run on_screen_changed to set the visual correctly initially.
on_screen_changed(&window, None);
window.connect_screen_changed(on_screen_changed);
let mut almost_empty_local_state = HashMap::new();
almost_empty_local_state.insert(
VarName("window_name".to_string()),
crate::value::AttrValue::from_primitive(window_name.to_string()),
);
let root_widget = &widgets::widget_use_to_gtk_widget(
&self.eww_config.get_widgets(),
&mut self.eww_state,
window_name,
&almost_empty_local_state,
&maplit::hashmap! { "window_name".into() => AttrValue::from_primitive(window_name.to_string()) },
&window_def.widget,
)?;
root_widget.get_style_context().add_class(&window_name.to_string());
@ -156,7 +158,7 @@ impl App {
window.show_all();
let gdk_window = window.get_window().context("couldn't get gdk window from gtk window")?;
gdk_window.set_override_redirect(true);
gdk_window.set_override_redirect(!window_def.focusable);
gdk_window.move_(actual_window_rect.x, actual_window_rect.y);
if window_def.stacking == WindowStacking::Foreground {

View file

@ -15,6 +15,7 @@ pub struct EwwWindowDefinition {
pub screen_number: Option<i32>,
pub widget: WidgetUse,
pub struts: Struts,
pub focusable: bool,
}
impl EwwWindowDefinition {
@ -28,6 +29,7 @@ impl EwwWindowDefinition {
let stacking = xml.attr("stacking").ok().map(|x| x.parse()).transpose()?.unwrap_or_default();
let screen_number = xml.attr("screen").ok().map(|x| x.parse()).transpose()?;
let focusable = xml.attr("focusable").ok().map(|x| x.parse()).transpose()?;
let struts = xml.child("struts").ok().map(Struts::from_xml_element).transpose()?;
let widget = WidgetUse::from_xml_node(xml.child("widget")?.only_child()?)?;
@ -37,6 +39,7 @@ impl EwwWindowDefinition {
widget,
stacking,
screen_number,
focusable: focusable.unwrap_or(false),
struts: struts.unwrap_or_default(),
})
}

View file

@ -21,6 +21,12 @@ impl std::borrow::Borrow<str> for VarName {
}
}
impl From<&str> for VarName {
fn from(s: &str) -> Self {
VarName(s.to_owned())
}
}
impl fmt::Debug for VarName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "VarName(\"{}\")", self.0)
@ -38,6 +44,12 @@ impl std::borrow::Borrow<str> for AttrName {
}
}
impl From<&str> for AttrName {
fn from(s: &str) -> Self {
AttrName(s.to_owned())
}
}
impl fmt::Debug for AttrName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "AttrName(\"{}\")", self.0)

View file

@ -223,15 +223,17 @@ fn build_gtk_scale(bargs: &mut BuilderArgs) -> Result<gtk::Scale> {
fn build_gtk_input(bargs: &mut BuilderArgs) -> Result<gtk::Entry> {
let gtk_widget = gtk::Entry::new();
let on_change_handler_id: Rc<RefCell<Option<glib::SignalHandlerId>>> = Rc::new(RefCell::new(None));
gtk_widget.set_editable(true);
gtk_widget.set_visible(true);
gtk_widget.set_text("fuck");
gtk_widget.set_can_focus(true);
resolve_block!(bargs, gtk_widget, {
// @prop value - the content of the text field
prop(value: as_string) {
gtk_widget.set_text(&value);
},
// @prop onchange - Command to run when the text changes. The placeholder `{}` will be replaced by the value
prop(onchange: as_string) {
let old_id = on_change_handler_id.replace(Some(
gtk_widget.connect_insert_text(move |_, text, _| {
run_command(&onchange, text);
gtk_widget.connect_changed(move |gtk_widget| {
run_command(&onchange, gtk_widget.get_text().to_string());
})
));
old_id.map(|id| gtk_widget.disconnect(id));