varie novità

master
Pietro Brenna 2021-05-12 13:58:06 +02:00
parent df3e820ccd
commit b9184566d1
4 changed files with 149 additions and 61 deletions

10
custom.css 100644
View File

@ -0,0 +1,10 @@
/*
È possibile digitare qui qualsiasi regola CSS riconosciuta da GTK+.
È possibile disabilitare temporaneamente questo CSS personalizzato facendo clic sul pulsante «Pausa».
Le modifiche sono applicate immediatamente e globalmente, per tutta l'applicazione.
*/
vte-terminal {
border: 3px solid red;
}

View File

@ -22,21 +22,46 @@ fn build_ui(application: &gtk::Application) {
if let Some(settings) = window.get_settings() { if let Some(settings) = window.get_settings() {
settings.set_property_gtk_enable_animations(false); settings.set_property_gtk_enable_animations(false);
} }
let w_state = WindowState::new_arc(WindowPos::Hidden, FullScreenState::NotFull);
let w_state0 = w_state.clone();
let w_state1 = w_state.clone();
let w_state2 = w_state.clone();
let w_state3 = w_state.clone();
let w_state4 = w_state.clone();
let w_state5 = w_state.clone();
let w_state6 = w_state.clone();
let w_state7 = w_state.clone();
window.set_title("First GTK+ Program"); window.set_title("Waydrop");
window.set_border_width(0); window.set_border_width(0);
window.move_(0, 0); window.move_(0, 0);
//window.maximize(); //window.maximize();
window.set_position(gtk::WindowPosition::None); window.set_position(gtk::WindowPosition::None);
window.set_type_hint(gdk::WindowTypeHint::Dock); window.set_type_hint(gdk::WindowTypeHint::Dock);
window.set_gravity(gdk::Gravity::NorthWest); window.set_gravity(gdk::Gravity::NorthWest);
window.set_default_size(1920, 500); window.set_default_size(1920, 700);
window.set_decorated(false); window.set_decorated(false);
window.set_can_focus(true); window.set_can_focus(true);
window.set_keep_above(true); window.set_keep_above(true);
let nb = gtk::Notebook::new(); let nb = gtk::Notebook::new();
nb.set_show_tabs(false); let css = gtk::CssProvider::new();
css.load_from_data(
br#"
notebook {
border-bottom: 1px solid #657b83;
}
vte-terminal {
padding: 0;
margin: 0;
}
"#,
)
.expect("Css errato");
let sc = window.get_screen().unwrap();
gtk::StyleContext::add_provider_for_screen(&sc, &css, 1000000);
nb.set_show_tabs(true);
nb.set_tab_pos(gtk::PositionType::Top);
nb.set_scrollable(true); nb.set_scrollable(true);
nb.set_show_border(false); nb.set_show_border(false);
let accel_group = gtk::AccelGroup::new(); let accel_group = gtk::AccelGroup::new();
@ -46,7 +71,7 @@ fn build_ui(application: &gtk::Application) {
modifier, modifier,
gtk::AccelFlags::VISIBLE, gtk::AccelFlags::VISIBLE,
clone!(@weak window, @weak nb => @default-return true, move |_accel_g, _window, _key, _modif| { clone!(@weak window, @weak nb => @default-return true, move |_accel_g, _window, _key, _modif| {
tabs::open_tab(&window, &nb, true, None, None, None); tabs::open_tab(&window, &nb, true, None, None, None, &w_state6);
true true
}), }),
); );
@ -108,12 +133,6 @@ fn build_ui(application: &gtk::Application) {
}), }),
); );
let (key, modifier) = gtk::accelerator_parse("F11"); let (key, modifier) = gtk::accelerator_parse("F11");
let w_state = WindowState::new_arc(WindowPos::Hidden, FullScreenState::NotFull);
let w_state0 = w_state.clone();
let w_state1 = w_state.clone();
let w_state2 = w_state.clone();
let w_state3 = w_state.clone();
let w_state4 = w_state.clone();
accel_group.connect_accel_group( accel_group.connect_accel_group(
key, key,
modifier, modifier,
@ -149,7 +168,7 @@ fn build_ui(application: &gtk::Application) {
window.add_accel_group(&accel_group); window.add_accel_group(&accel_group);
window.add(&nb); window.add(&nb);
if let Ok(first_tab) = tabs::build_tab(&nb, None, None) { if let Ok(first_tab) = tabs::build_tab(&nb, None, None, &w_state5) {
tabs::go_to_tab(&window, &nb, &first_tab); tabs::go_to_tab(&window, &nb, &first_tab);
} }
window.set_skip_taskbar_hint(true); window.set_skip_taskbar_hint(true);
@ -176,13 +195,13 @@ fn build_ui(application: &gtk::Application) {
nb.connect_page_removed(clone!(@weak window => move |notebook, _vte, _index| { nb.connect_page_removed(clone!(@weak window => move |notebook, _vte, _index| {
if notebook.get_n_pages() == 0 { if notebook.get_n_pages() == 0 {
if w_state0.get_pos() != WindowPos::Closing { if w_state0.get_pos() != WindowPos::Closing {
crate::tabs::open_tab(&window, &notebook, false,None, None, None); crate::tabs::open_tab(&window, &notebook, false,None, None, None, &w_state5);
window_state::hide(&window, &w_state0); window_state::hide(&window, &w_state0);
} }
} else { } else {
tabs::set_titles(&notebook); tabs::set_titles(&notebook);
if notebook.get_n_pages() == 1 { if notebook.get_n_pages() == 1 {
notebook.set_show_tabs(false); notebook.set_show_tabs(true);
} }
} }
})); }));
@ -209,11 +228,11 @@ fn build_ui(application: &gtk::Application) {
} }
RunShell { cwd, shell } => { RunShell { cwd, shell } => {
tira_su(); tira_su();
tabs::open_tab(&window, &nb, true, cwd, Some(shell), None); tabs::open_tab(&window, &nb, true, cwd, Some(shell), None, &w_state7);
} }
RunInDefaultShell { cwd, command } => { RunInDefaultShell { cwd, command } => {
tira_su(); tira_su();
tabs::open_tab(&window, &nb, true, cwd, None, Some(command)); tabs::open_tab(&window, &nb, true, cwd, None, Some(command), &w_state7);
} }
RunInCustomShell { RunInCustomShell {
cwd, cwd,
@ -221,7 +240,7 @@ fn build_ui(application: &gtk::Application) {
command, command,
} => { } => {
tira_su(); tira_su();
tabs::open_tab(&window, &nb, true, cwd, Some(shell), Some(command)); tabs::open_tab(&window, &nb, true, cwd, Some(shell), Some(command), &w_state7);
} }
} }
glib::Continue(true) glib::Continue(true)

View File

@ -3,16 +3,30 @@ use gtk::prelude::*;
use std::{env::var, path::Path}; use std::{env::var, path::Path};
use vte::TerminalExt; use vte::TerminalExt;
use crate::window_state::{RcState, StateOperations};
pub fn build_tab( pub fn build_tab(
nb: &gtk::Notebook, nb: &gtk::Notebook,
cwd: Option<String>, cwd: Option<String>,
shell: Option<Vec<String>>, shell: Option<Vec<String>>,
w_state: &RcState,
) -> Result<vte::Terminal, glib::Error> { ) -> Result<vte::Terminal, glib::Error> {
let l = gtk::Label::new(Some("~")); let l = gtk::Label::new(Some("~"));
l.set_ellipsize(pango::EllipsizeMode::Middle); l.set_ellipsize(pango::EllipsizeMode::Middle);
//gtk::Window::set_interactive_debugging(true); //gtk::Window::set_interactive_debugging(true);
let vte = vte::Terminal::new(); let vte = vte::Terminal::new();
vte.set_scrollback_lines(-1); vte.set_scrollback_lines(-1);
// let sty = vte.get_style_context();
// let css = gtk::CssProvider::new();
// css.load_from_data(
// br#"
// * {
// padding: 10px;
// margin: 10px;
// }"#,
// )
// .expect("errore css");
// sty.add_provider(&css, 10000);
let font = pango::FontDescription::from_string("Iosevka Regular 13"); let font = pango::FontDescription::from_string("Iosevka Regular 13");
vte.set_font(Some(&font)); vte.set_font(Some(&font));
@ -51,6 +65,18 @@ pub fn build_tab(
} }
gtk::Inhibit(false) gtk::Inhibit(false)
}); });
let wsc1 = w_state.clone();
let wsc2 = w_state.clone();
w_state.set_char_h(Some(vte.get_char_height() as u64));
vte.connect_char_size_changed(move | _vte, _w, h| {
wsc1.set_char_h(Some(h as u64));
});
let nb2 = nb.clone();
vte.connect_realize(move |vte|{
let h = vte.get_allocated_size();
let hn = nb2.get_allocated_size();
wsc2.set_tab_h(Some((hn.0.height - h.0.height) as u64));
});
vte.connect_window_title_changed(clone!(@weak nb => move |term| { vte.connect_window_title_changed(clone!(@weak nb => move |term| {
set_title(term, &nb); set_title(term, &nb);
@ -58,25 +84,25 @@ pub fn build_tab(
// Setto colori terminale // Setto colori terminale
use glib::translate::ToGlibPtr; use glib::translate::ToGlibPtr;
use std::str::FromStr; use std::str::FromStr;
let fg = gdk::RGBA::from_str("#c5c5c8c8c6c6").unwrap_or(gdk::RGBA::white()); let fg = gdk::RGBA::from_str("#65657b7b8383").unwrap_or(gdk::RGBA::white());
let bg = gdk::RGBA::from_str("#1d1d1f1f2121").unwrap_or(gdk::RGBA::black()); let bg = gdk::RGBA::from_str("#fdfdf6f6e3e3").unwrap_or(gdk::RGBA::black());
let palette = (&[ let palette = (&[
"#1d1d1f1f2121", "#070736364242",
"#cccc66666666", "#dcdc32322f2f",
"#b5b5bdbd6868", "#858599990000",
"#f0f0c6c67474", "#b5b589890000",
"#8181a2a2bebe", "#26268b8bd2d2",
"#b2b29494bbbb", "#d3d336368282",
"#8a8abebeb7b7", "#2a2aa1a19898",
"#c5c5c8c8c6c6", "#eeeee8e8d5d5",
"#969698989696", "#00002b2b3636",
"#cccc66666666", "#cbcb4b4b1616",
"#b5b5bdbd6868", "#58586e6e7575",
"#f0f0c6c67474", "#65657b7b8383",
"#8181a2a2bebe", "#838394949696",
"#b2b29494bbbb", "#6c6c7171c4c4",
"#8a8abebeb7b7", "#9393a1a1a1a1",
"#ffffffffffff", "#fdfdf6f6e3e3",
]) ])
.iter() .iter()
.map(|&s| gdk::RGBA::from_str(s).unwrap_or(gdk::RGBA::from_str("#ffffff").unwrap())); .map(|&s| gdk::RGBA::from_str(s).unwrap_or(gdk::RGBA::from_str("#ffffff").unwrap()));
@ -93,10 +119,9 @@ pub fn build_tab(
Ok(vte) Ok(vte)
} }
fn set_title(term: &vte::Terminal, nb: &gtk::Notebook) { fn set_title(term: &vte::Terminal, nb: &gtk::Notebook) {
let tab_n = if let Some(num) = nb.page_num(term) { let tab_n = match nb.page_num(term) {
format!("{}. ", num + 1) Some(num) => format!("{}. ", num + 1),
} else { None => "".to_string(),
"".to_string()
}; };
if let Some(l) = nb.get_tab_label(term) { if let Some(l) = nb.get_tab_label(term) {
if let Ok(l) = l.downcast::<gtk::Label>() { if let Ok(l) = l.downcast::<gtk::Label>() {
@ -146,8 +171,9 @@ pub fn open_tab(
cwd: Option<String>, cwd: Option<String>,
shell: Option<Vec<String>>, shell: Option<Vec<String>>,
inject_command: Option<String>, inject_command: Option<String>,
w_state: &RcState,
) { ) {
let new_tab = build_tab(nb, cwd, shell); let new_tab = build_tab(nb, cwd, shell, w_state);
if let Ok(new_tab) = new_tab { if let Ok(new_tab) = new_tab {
window.show_all(); window.show_all();
if focus { if focus {

View File

@ -1,7 +1,6 @@
use gdk::WindowExt; use gdk::WindowExt;
use gtk::prelude::*; use gtk::prelude::*;
use std::rc::Rc; use std::sync::{Arc, RwLock};
use std::sync::RwLock;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
#[derive(Eq, PartialEq, Debug, Copy, Clone)] #[derive(Eq, PartialEq, Debug, Copy, Clone)]
@ -24,14 +23,19 @@ pub use FullScreenState::*;
pub use WindowPos::*; pub use WindowPos::*;
pub struct WindowState { pub struct WindowState {
position: WindowPos, position: WindowPos,
char_h: Option<u64>,
tab_h: Option<u64>,
full: FullScreenState, full: FullScreenState,
last_toggle: Option<Instant>, last_toggle: Option<Instant>,
focus_lost: Option<Instant>, focus_lost: Option<Instant>,
} }
pub type RcState = Arc<RwLock<WindowState>>;
impl WindowState { impl WindowState {
pub fn new_arc(p: WindowPos, f: FullScreenState) -> Rc<RwLock<Self>> { pub fn new_arc(p: WindowPos, f: FullScreenState) -> RcState {
Rc::new(RwLock::new(WindowState { Arc::new(RwLock::new(WindowState {
full: f, full: f,
char_h: None,
tab_h: None,
position: p, position: p,
last_toggle: None, last_toggle: None,
focus_lost: None, focus_lost: None,
@ -43,12 +47,16 @@ pub trait StateOperations {
fn get_pos(&self) -> WindowPos; fn get_pos(&self) -> WindowPos;
fn set_full(&self, f: FullScreenState); fn set_full(&self, f: FullScreenState);
fn get_full(&self) -> FullScreenState; fn get_full(&self) -> FullScreenState;
fn get_char_h(&self) -> Option<u64>;
fn set_char_h(&self, char_h: Option<u64>);
fn get_tab_h(&self) -> Option<u64>;
fn set_tab_h(&self, tab_h: Option<u64>);
fn set_last_toggle(&self, instant: Option<Instant>); fn set_last_toggle(&self, instant: Option<Instant>);
fn get_last_toggle(&self) -> Option<Instant>; fn get_last_toggle(&self) -> Option<Instant>;
fn set_focus_lost(&self, instant: Option<Instant>); fn set_focus_lost(&self, instant: Option<Instant>);
fn get_focus_lost(&self) -> Option<Instant>; fn get_focus_lost(&self) -> Option<Instant>;
} }
impl StateOperations for Rc<RwLock<WindowState>> { impl StateOperations for RcState {
fn set_pos(&self, p: WindowPos) { fn set_pos(&self, p: WindowPos) {
if let Ok(mut w_lock) = self.write() { if let Ok(mut w_lock) = self.write() {
w_lock.position = p; w_lock.position = p;
@ -77,6 +85,20 @@ impl StateOperations for Rc<RwLock<WindowState>> {
FullScreenState::Unknown FullScreenState::Unknown
} }
} }
fn get_char_h(&self) -> Option<u64> {
if let Ok(r_lock) = self.read() {
r_lock.char_h
} else {
None
}
}
fn get_tab_h(&self) -> Option<u64> {
if let Ok(r_lock) = self.read() {
r_lock.tab_h
} else {
None
}
}
fn get_last_toggle(&self) -> Option<Instant> { fn get_last_toggle(&self) -> Option<Instant> {
if let Ok(r_lock) = self.read() { if let Ok(r_lock) = self.read() {
r_lock.last_toggle r_lock.last_toggle
@ -105,9 +127,23 @@ impl StateOperations for Rc<RwLock<WindowState>> {
eprintln!("Can't acquire lock"); eprintln!("Can't acquire lock");
} }
} }
fn set_char_h(&self, char_h: Option<u64>) {
if let Ok(mut w_lock) = self.write() {
w_lock.char_h = char_h;
} else {
eprintln!("Can't acquire lock");
}
}
fn set_tab_h(&self, tab_h: Option<u64>) {
if let Ok(mut w_lock) = self.write() {
w_lock.tab_h = tab_h;
} else {
eprintln!("Can't acquire lock");
}
}
} }
pub fn bring_up(window: &gtk::ApplicationWindow, w_state: &Rc<RwLock<WindowState>>, ts: u32) { pub fn bring_up(window: &gtk::ApplicationWindow, w_state: &RcState, ts: u32) {
if let Some(instant) = w_state.get_last_toggle() { if let Some(instant) = w_state.get_last_toggle() {
if instant.elapsed() < Duration::from_millis(300) { if instant.elapsed() < Duration::from_millis(300) {
return; return;
@ -141,7 +177,7 @@ pub fn bring_up(window: &gtk::ApplicationWindow, w_state: &Rc<RwLock<WindowState
gdk_window.focus(ts); gdk_window.focus(ts);
gdk_window.focus(0); gdk_window.focus(0);
} }
let s = calc_w_h(window); let s = calc_w_h(window, w_state);
window.get_window().map(|w| w.resize(s.0, s.1)); window.get_window().map(|w| w.resize(s.0, s.1));
None None
} }
@ -152,16 +188,12 @@ pub fn bring_up(window: &gtk::ApplicationWindow, w_state: &Rc<RwLock<WindowState
} }
} }
pub fn hide(window: &gtk::ApplicationWindow, stato: &Rc<RwLock<WindowState>>) { pub fn hide(window: &gtk::ApplicationWindow, stato: &RcState) {
stato.set_pos(Hiding); stato.set_pos(Hiding);
window.hide(); window.hide();
} }
pub fn esegui_toggle( pub fn esegui_toggle(window: &gtk::ApplicationWindow, nb: &gtk::Notebook, w_state: &RcState) {
window: &gtk::ApplicationWindow,
nb: &gtk::Notebook,
w_state: &Rc<RwLock<WindowState>>,
) {
let ts = gtk::get_current_event_time(); let ts = gtk::get_current_event_time();
let pos = w_state.get_pos(); let pos = w_state.get_pos();
match pos { match pos {
@ -183,7 +215,7 @@ pub fn esegui_toggle(
} }
} }
pub fn focus_out(w_state: &Rc<RwLock<WindowState>>) -> gtk::Inhibit { pub fn focus_out(w_state: &RcState) -> gtk::Inhibit {
// eprintln!("<<<<<<<<<<<< Focus out!"); // eprintln!("<<<<<<<<<<<< Focus out!");
w_state.set_focus_lost(Some(Instant::now())); w_state.set_focus_lost(Some(Instant::now()));
let pos = w_state.get_pos(); let pos = w_state.get_pos();
@ -198,13 +230,10 @@ pub fn focus_out(w_state: &Rc<RwLock<WindowState>>) -> gtk::Inhibit {
gtk::Inhibit(false) gtk::Inhibit(false)
} }
pub fn focus_in( pub fn focus_in(window: &gtk::ApplicationWindow, w_state: &RcState) -> gtk::Inhibit {
window: &gtk::ApplicationWindow,
w_state: &Rc<RwLock<WindowState>>,
) -> gtk::Inhibit {
//eprintln!(">>>>>>>>>>> Focus in!"); //eprintln!(">>>>>>>>>>> Focus in!");
w_state.set_pos(Up); w_state.set_pos(Up);
let s = calc_w_h(window); let s = calc_w_h(window, w_state);
window.set_type_hint(gdk::WindowTypeHint::Dock); window.set_type_hint(gdk::WindowTypeHint::Dock);
if let Some((_x, _y, width, height)) = window.get_window().and_then(|x| Some(x.get_geometry())) if let Some((_x, _y, width, height)) = window.get_window().and_then(|x| Some(x.get_geometry()))
{ {
@ -218,11 +247,15 @@ pub fn focus_in(
gtk::Inhibit(false) gtk::Inhibit(false)
} }
pub fn calc_w_h(window: &gtk::ApplicationWindow) -> (i32, i32) { pub fn calc_w_h(window: &gtk::ApplicationWindow, w_state: &RcState) -> (i32, i32) {
window //let (rounding, tab_h) = w_state.get_char_tab_h();
let rounding = w_state.get_char_h().unwrap() as i32;
let tab_h = w_state.get_tab_h().unwrap() as i32;
let wh = window
.get_window() .get_window()
.and_then(|gdk_win| gdk_win.get_display().get_monitor_at_window(&gdk_win)) .and_then(|gdk_win| gdk_win.get_display().get_monitor_at_window(&gdk_win))
.map(|mon| mon.get_geometry()) .map(|mon| mon.get_geometry())
.and_then(|gdk::Rectangle { width, height, .. }| Some((width, height / 2))) .and_then(|gdk::Rectangle { width, height, .. }| Some((width, height / 2)))
.unwrap_or((1920, 540)) .unwrap_or((1920, 540));
(wh.0, wh.1 - wh.1 % rounding + tab_h)
} }