Implement selectable windows, fixes #27
This commit is contained in:
parent
4bbbfe7eab
commit
a906c18bd7
4 changed files with 39 additions and 20 deletions
30
src/app.rs
30
src/app.rs
|
@ -4,14 +4,13 @@ use crate::{
|
||||||
eww_state,
|
eww_state,
|
||||||
script_var_handler::*,
|
script_var_handler::*,
|
||||||
util,
|
util,
|
||||||
value::{Coords, NumWithUnit, PrimitiveValue, VarName},
|
value::{AttrValue, Coords, NumWithUnit, PrimitiveValue, VarName},
|
||||||
widgets,
|
widgets,
|
||||||
};
|
};
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
use crossbeam_channel;
|
use crossbeam_channel;
|
||||||
use debug_stub_derive::*;
|
use debug_stub_derive::*;
|
||||||
use gdk::WindowExt;
|
use gdk::WindowExt;
|
||||||
use glib::Cast;
|
|
||||||
use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt};
|
use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
@ -109,7 +108,7 @@ impl App {
|
||||||
.eww_config
|
.eww_config
|
||||||
.get_windows()
|
.get_windows()
|
||||||
.get(window_name)
|
.get(window_name)
|
||||||
.context(format!("No window named '{}' defined", window_name))?
|
.with_context(|| format!("No window named '{}' defined", window_name))?
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let display = gdk::Display::get_default().expect("could not get default display");
|
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);
|
let monitor_geometry = display.get_default_screen().get_monitor_geometry(*screen_number);
|
||||||
|
|
||||||
window_def.position = pos.unwrap_or_else(|| window_def.position);
|
window_def.position = pos.unwrap_or(window_def.position);
|
||||||
window_def.size = size.unwrap_or_else(|| window_def.size);
|
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 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));
|
window.set_title(&format!("Eww - {}", window_name));
|
||||||
let wm_class_name = format!("eww-{}", window_name);
|
let wm_class_name = format!("eww-{}", window_name);
|
||||||
window.set_wmclass(&wm_class_name, &wm_class_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_position(gtk::WindowPosition::Center);
|
||||||
window.set_default_size(actual_window_rect.width, actual_window_rect.height);
|
window.set_default_size(actual_window_rect.width, actual_window_rect.height);
|
||||||
window.set_size_request(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.
|
// run on_screen_changed to set the visual correctly initially.
|
||||||
on_screen_changed(&window, None);
|
on_screen_changed(&window, None);
|
||||||
window.connect_screen_changed(on_screen_changed);
|
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(
|
let root_widget = &widgets::widget_use_to_gtk_widget(
|
||||||
&self.eww_config.get_widgets(),
|
&self.eww_config.get_widgets(),
|
||||||
&mut self.eww_state,
|
&mut self.eww_state,
|
||||||
window_name,
|
window_name,
|
||||||
&almost_empty_local_state,
|
&maplit::hashmap! { "window_name".into() => AttrValue::from_primitive(window_name.to_string()) },
|
||||||
&window_def.widget,
|
&window_def.widget,
|
||||||
)?;
|
)?;
|
||||||
root_widget.get_style_context().add_class(&window_name.to_string());
|
root_widget.get_style_context().add_class(&window_name.to_string());
|
||||||
|
@ -156,7 +158,7 @@ impl App {
|
||||||
window.show_all();
|
window.show_all();
|
||||||
|
|
||||||
let gdk_window = window.get_window().context("couldn't get gdk window from gtk window")?;
|
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);
|
gdk_window.move_(actual_window_rect.x, actual_window_rect.y);
|
||||||
|
|
||||||
if window_def.stacking == WindowStacking::Foreground {
|
if window_def.stacking == WindowStacking::Foreground {
|
||||||
|
|
|
@ -15,6 +15,7 @@ pub struct EwwWindowDefinition {
|
||||||
pub screen_number: Option<i32>,
|
pub screen_number: Option<i32>,
|
||||||
pub widget: WidgetUse,
|
pub widget: WidgetUse,
|
||||||
pub struts: Struts,
|
pub struts: Struts,
|
||||||
|
pub focusable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EwwWindowDefinition {
|
impl EwwWindowDefinition {
|
||||||
|
@ -28,6 +29,7 @@ impl EwwWindowDefinition {
|
||||||
|
|
||||||
let stacking = xml.attr("stacking").ok().map(|x| x.parse()).transpose()?.unwrap_or_default();
|
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 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 struts = xml.child("struts").ok().map(Struts::from_xml_element).transpose()?;
|
||||||
|
|
||||||
let widget = WidgetUse::from_xml_node(xml.child("widget")?.only_child()?)?;
|
let widget = WidgetUse::from_xml_node(xml.child("widget")?.only_child()?)?;
|
||||||
|
@ -37,6 +39,7 @@ impl EwwWindowDefinition {
|
||||||
widget,
|
widget,
|
||||||
stacking,
|
stacking,
|
||||||
screen_number,
|
screen_number,
|
||||||
|
focusable: focusable.unwrap_or(false),
|
||||||
struts: struts.unwrap_or_default(),
|
struts: struts.unwrap_or_default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
impl fmt::Debug for VarName {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "VarName(\"{}\")", self.0)
|
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 {
|
impl fmt::Debug for AttrName {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "AttrName(\"{}\")", self.0)
|
write!(f, "AttrName(\"{}\")", self.0)
|
||||||
|
|
|
@ -223,15 +223,17 @@ fn build_gtk_scale(bargs: &mut BuilderArgs) -> Result<gtk::Scale> {
|
||||||
fn build_gtk_input(bargs: &mut BuilderArgs) -> Result<gtk::Entry> {
|
fn build_gtk_input(bargs: &mut BuilderArgs) -> Result<gtk::Entry> {
|
||||||
let gtk_widget = gtk::Entry::new();
|
let gtk_widget = gtk::Entry::new();
|
||||||
let on_change_handler_id: Rc<RefCell<Option<glib::SignalHandlerId>>> = Rc::new(RefCell::new(None));
|
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, {
|
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) {
|
prop(onchange: as_string) {
|
||||||
let old_id = on_change_handler_id.replace(Some(
|
let old_id = on_change_handler_id.replace(Some(
|
||||||
gtk_widget.connect_insert_text(move |_, text, _| {
|
gtk_widget.connect_changed(move |gtk_widget| {
|
||||||
run_command(&onchange, text);
|
run_command(&onchange, gtk_widget.get_text().to_string());
|
||||||
})
|
})
|
||||||
));
|
));
|
||||||
old_id.map(|id| gtk_widget.disconnect(id));
|
old_id.map(|id| gtk_widget.disconnect(id));
|
||||||
|
|
Loading…
Add table
Reference in a new issue