Tante cose

master
Pietro Brenna 2020-03-15 15:46:19 +01:00
parent 296985d382
commit 454f84c5ae
9 changed files with 389 additions and 110 deletions

32
Cargo.lock generated
View File

@ -96,6 +96,25 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "dbus"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acd824d45fad5ff0e178fcb3c040f13780e73f63a0a6d5cde59e7894f251ab0e"
dependencies = [
"libc",
"libdbus-sys",
]
[[package]]
name = "dbus-macros"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efc7077f517382c729c845ea59d2e36a9946f5e0dd837e589a287d87535a4730"
dependencies = [
"dbus",
]
[[package]]
name = "futures-channel"
version = "0.3.4"
@ -352,6 +371,15 @@ version = "0.2.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
[[package]]
name = "libdbus-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8720f9274907052cb50313f91201597868da9d625f8dd125f2aca5bddb7e83a1"
dependencies = [
"pkg-config",
]
[[package]]
name = "maybe-uninit"
version = "2.0.0"
@ -499,10 +527,14 @@ name = "waydrop"
version = "0.1.0"
dependencies = [
"crossbeam-channel",
"dbus",
"dbus-macros",
"gdk",
"gdk-sys",
"gio",
"gio-sys",
"glib",
"glib-sys",
"gtk",
"pango",
"vte-rs",

View File

@ -7,20 +7,28 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
vte-rs = "*"
vte-rs = "^0.3"
vte-sys = "*"
gio = "*"
gtk = "*"
gio-sys = "*"
gtk = {version = "*", features = ["v3_22"]}
gdk-sys="*"
gdk = "*"
pango = "*"
crossbeam-channel="*"
glib = "*"
glib-sys = "*"
# jsonrpc-ipc-server = "^14.0"
# jsonrpc-derive = "*"
# jsonrpc-core = "*"
# jsonrpc-core-client = "*"
dbus = "*"
dbus-macros = "*"
[[bin]]
name = "waydrop"
path = "src/main.rs"
[[bin]]
name = "wake"
path = "src/wake.rs"
name = "waydrop-toggle"
path = "src/toggle.rs"

View File

@ -6,7 +6,6 @@ use gio::prelude::*;
use gtk::prelude::*;
use glib::clone;
use glib::translate::{ToGlib, ToGlibPtr};
use gtk::SettingsExt;
use std::env::args;
use std::sync::{Arc, RwLock};
@ -26,6 +25,10 @@ fn build_ui(application: &gtk::Application) {
window.set_title("First GTK+ Program");
window.set_border_width(0);
window.move_(0, 0);
//window.maximize();
window.set_position(gtk::WindowPosition::None);
window.set_type_hint(gdk::WindowTypeHint::Dock);
window.set_gravity(gdk::Gravity::NorthWest);
window.set_default_size(1920, 500);
window.set_decorated(false);
@ -41,19 +44,71 @@ fn build_ui(application: &gtk::Application) {
modifier,
gtk::AccelFlags::VISIBLE,
clone!(@weak window, @weak nb => @default-return true, move |accel_g, _window, _key, _modif| {
tabs::apri_tab(&window, &nb, &accel_g, true);
tabs::apri_tab(&window, &nb, true, None, None, None);
true
}),
);
let (key, modifier) = gtk::accelerator_parse("<Control>Page_Down");
accel_group.connect_accel_group(
key,
modifier,
gtk::AccelFlags::VISIBLE,
clone!(@weak nb => @default-return true, move |_accel_g, _window, _key, _modif| {
nb.next_page();
true
}),
);
let (key, modifier) = gtk::accelerator_parse("<Control>Page_Up");
accel_group.connect_accel_group(
key,
modifier,
gtk::AccelFlags::VISIBLE,
clone!(@weak nb => @default-return true, move |_accel_g, _window, _key, _modif| {
nb.prev_page();
true
}),
);
let (key, modifier) = gtk::accelerator_parse("F11");
let full_screen = Arc::new(RwLock::new(false));
accel_group.connect_accel_group(
key,
modifier,
gtk::AccelFlags::VISIBLE,
clone!(@weak window => @default-return true, move |_accel_g, _win, _key, _modif| {
if let Ok(mut lock) = full_screen.write(){
if *lock {
window.unfullscreen();
} else {
window.fullscreen();
}
*lock = !*lock;
}
true
}),
);
for i in 1..9 {
let (key, modifier) = gtk::accelerator_parse(&format!("<Alt>{}", i));
accel_group.connect_accel_group(
key,
modifier,
gtk::AccelFlags::VISIBLE,
clone!(@weak nb => @default-return true, move |_accel_g, _win, _key, _modif| {
nb.set_current_page(Some(i-1));
true
}),
);
}
window.add_accel_group(&accel_group);
window.add(&nb);
let first_tab = tabs::build_tab(&nb, &accel_group);
if let Ok(first_tab) = tabs::build_tab(&window, &nb, None, None) {
tabs::passa_a_tab(&window, &nb, &first_tab);
}
window.set_skip_taskbar_hint(true);
window.set_skip_pager_hint(true);
window.show_all();
tabs::passa_a_tab(&window, &nb, &first_tab);
unsafe {
/*unsafe {
gdk_sys::gdk_window_set_skip_pager_hint(
window.get_window().unwrap().to_glib_none().0,
true.to_glib(),
@ -62,43 +117,93 @@ fn build_ui(application: &gtk::Application) {
window.get_window().unwrap().to_glib_none().0,
true.to_glib(),
);
}
}*/
let stato = Arc::new(RwLock::new(stato_finestra::StatoFinestra::Su));
let stato0 = stato.clone();
let stato1 = stato.clone();
let stato2 = stato.clone();
let stato3 = stato.clone();
let stato4 = stato.clone();
//let cloned_app = application.clone();
window.connect_focus_out_event(move |_widget, _b| stato_finestra::focus_out(&stato1));
window.connect_focus_in_event(move |_widget, _b| stato_finestra::focus_in(&stato2));
nb.connect_page_removed(clone!(@weak window, @weak accel_group => move |notebook, _vte, _index| {
if notebook.get_n_pages() == 0 {
if let Ok(ref mut lock_stato) = stato.write() {
tabs::apri_tab(&window, &notebook, &accel_group, false);
stato_finestra::butta_giu(&window, lock_stato);
window.connect_focus_in_event(clone!(@weak window => @default-return gtk::Inhibit(false),
move |_widget, _b| stato_finestra::focus_in(&window, &stato2)));
nb.connect_destroy(move |_nb| {
if let Ok(mut lock_stato) = stato.write() {
*lock_stato = stato_finestra::StatoFinestra::Chiudendo;
}
} else if notebook.get_n_pages() == 1 {
});
nb.connect_page_removed(
clone!(@weak window => move |notebook, _vte, _index| {
if notebook.get_n_pages() == 0 {
if let Ok(mut lock_stato) = stato0.write() {
if *lock_stato != stato_finestra::StatoFinestra::Chiudendo {
crate::tabs::apri_tab(&window, &notebook, false,None, None, None);
stato_finestra::butta_giu(&window, &mut lock_stato);
}
}
} else {
tabs::set_titles(&notebook);
if notebook.get_n_pages() == 1 {
notebook.set_show_tabs(false);
}
}));
nb.connect_page_added(move |notebook, _vte, _index|{
}
dbg!();
}),
);
nb.connect_page_added(move |notebook, _vte, _index| {
if notebook.get_n_pages() > 1 {
notebook.set_show_tabs(true);
}
});
nb.connect_page_reordered(move |notebook, _vte, _index| {
tabs::set_titles(&notebook);
});
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
if let Ok(ref mut lock_stato) = stato4.write() {
stato_finestra::tira_su(&window, lock_stato, gtk::get_current_event_time());
}
//tabs::focus_tab_corrente(&nb);
rx.attach(None, move |_cmd| {
stato_finestra::esegui_toggle(&window, &nb, &stato3)
rx.attach(None, move |cmd| {
let tira_su = || {
if let Ok(ref mut lock_stato) = stato3.write() {
stato_finestra::tira_su(&window, lock_stato, gtk::get_current_event_time());
}
};
use wake_listener::RpcCommand::*;
match cmd {
Toggle => {
stato_finestra::esegui_toggle(&window, &nb, &stato3);
}
RunShell { cwd, shell } => {
tira_su();
tabs::apri_tab(&window, &nb, true, cwd, Some(shell), None);
}
RunInDefaultShell { cwd, command } => {
tira_su();
tabs::apri_tab(&window, &nb, true, cwd, None, Some(command));
}
RunInCustomShell {
cwd,
shell,
command,
} => {
tira_su();
tabs::apri_tab(
&window,
&nb,
true,
cwd,
Some(shell),
Some(command),
);
}
}
glib::Continue(true)
});
thread::spawn(move || {
wake_listener::listener(&tx);
wake_listener::listener(tx);
});
}

View File

@ -5,21 +5,44 @@ pub enum StatoFinestra {
Nascondendo,
Nascosta,
SuNonFocusata,
Chiudendo,
}
use gdk::WindowExt;
use gtk::prelude::*;
use std::sync::{Arc, RwLock};
pub fn tira_su(window: &gtk::ApplicationWindow, stato: &mut StatoFinestra, ts: u32) {
match *stato {
StatoFinestra::Nascosta | StatoFinestra::Nascondendo => {
// Shameless copy from guake
/*window.hide();
window.present();
window.deiconify();
window.deiconify();*/
window.show();
window.get_window().unwrap().focus(ts);
let gdk_window = window.get_window();
if let Some(ref gdk_window) = gdk_window {
gdk_window.focus(ts);
}
window.set_type_hint(gdk::WindowTypeHint::Dock);
window.set_type_hint(gdk::WindowTypeHint::Normal);
window.get_window().unwrap().focus(0);
/*if let Some(ref gdk_window) = gdk_window {
gdk_window.focus(0);
}*/
*stato = StatoFinestra::TirandoSu;
}
StatoFinestra::SuNonFocusata => {
window.hide();
window.show();
let gdk_window = window.get_window();
if let Some(ref gdk_window) = gdk_window {
gdk_window.focus(ts);
gdk_window.focus(0);
}
let s = calc_w_h(window);
window.get_window().map(|w| w.resize(s.0, s.1));
*stato = StatoFinestra::Su;
}
_ => {}
}
}
pub fn butta_giu(window: &gtk::ApplicationWindow, stato: &mut StatoFinestra) {
@ -31,32 +54,20 @@ pub fn esegui_toggle(
window: &gtk::ApplicationWindow,
nb: &gtk::Notebook,
stato: &Arc<RwLock<StatoFinestra>>,
) -> glib::source::Continue {
) {
let ts = gtk::get_current_event_time();
if let Ok(mut inner) = stato.write() {
match *inner {
StatoFinestra::Nascosta | StatoFinestra::Nascondendo => {
StatoFinestra::Nascosta | StatoFinestra::Nascondendo | StatoFinestra::SuNonFocusata => {
tira_su(window, &mut inner, ts);
crate::tabs::focus_tab_corrente(&nb);
}
StatoFinestra::SuNonFocusata => {
window.hide();
window.show();
window.get_window().unwrap().focus(ts);
window.get_window().unwrap().focus(0);
crate::tabs::focus_tab_corrente(&nb);
*inner = StatoFinestra::Su;
}
StatoFinestra::Su => {
butta_giu(window, &mut inner)
}
StatoFinestra::Su => butta_giu(window, &mut inner),
_ => {}
}
} else {
eprintln!("Can't acquire lock!");
}
println!("Stato: {:?}", stato);
glib::Continue(true)
}
pub fn focus_out(stato: &Arc<RwLock<StatoFinestra>>) -> gtk::Inhibit {
@ -68,14 +79,35 @@ pub fn focus_out(stato: &Arc<RwLock<StatoFinestra>>) -> gtk::Inhibit {
//widget.unstick();
}
}
println!("Stato: {:?}", stato);
gtk::Inhibit(false)
}
pub fn focus_in(stato: &Arc<RwLock<StatoFinestra>>) -> gtk::Inhibit {
pub fn focus_in(
window: &gtk::ApplicationWindow,
stato: &Arc<RwLock<StatoFinestra>>,
) -> gtk::Inhibit {
if let Ok(mut inner) = stato.write() {
*inner = StatoFinestra::Su;
}
println!("Stato: {:?}", stato);
let s = calc_w_h(window);
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 height != s.1 || width != s.0 {
window.hide();
window.resize( s.0, s.1);
window.show();
window.move_(0,0);
}
}
gtk::Inhibit(false)
}
pub fn calc_w_h(window: &gtk::ApplicationWindow) -> (i32, i32) {
window
.get_window()
.and_then(|gdk_win| gdk_win.get_display().get_monitor_at_window(&gdk_win))
.map(|mon| mon.get_geometry())
.and_then(|gdk::Rectangle { width, height, .. }| Some((width, height / 2)))
.unwrap_or((1920, 540))
}

View File

@ -1,17 +1,24 @@
use glib::clone;
use gtk::prelude::*;
use std::{env::var, path::Path};
use vte::TerminalExt;
pub fn build_tab(nb: &gtk::Notebook, w_accel_group: &gtk::AccelGroup) -> vte::Terminal {
pub fn build_tab(
window: &gtk::ApplicationWindow,
nb: &gtk::Notebook,
cwd: Option<String>,
shell: Option<Vec<String>>,
) -> Result<vte::Terminal, glib::Error> {
let new_accel_g = gtk::AccelGroup::new();
let l = gtk::Label::new(Some("~"));
l.set_width_chars(10);
l.set_ellipsize(pango::EllipsizeMode::Start);
l.set_width_chars(14);
l.set_ellipsize(pango::EllipsizeMode::Middle);
//gtk::Window::set_interactive_debugging(true);
let vte = vte::Terminal::new();
let (key, modifier) = gtk::accelerator_parse("<Control><Shift>c");
vte.add_accelerator(
"copy-clipboard",
w_accel_group,
&new_accel_g,
key,
modifier,
gtk::AccelFlags::VISIBLE,
@ -20,22 +27,28 @@ pub fn build_tab(nb: &gtk::Notebook, w_accel_group: &gtk::AccelGroup) -> vte::Te
let font = pango::FontDescription::from_string("Iosevka Regular 13");
vte.set_font(Some(&font));
let c = gio::Cancellable::get_current();
let pid = vte
.spawn_sync(
let shell = shell.unwrap_or(vec![var("SHELL").unwrap_or("/bin/sh".to_string())]);
let shell: Vec<_> = shell.iter().map(Path::new).collect();
let stringa: String;
let cwd = if cwd.is_some() {
stringa = cwd.unwrap();
Some(stringa.as_str())
} else {
None
};
let _pid = vte.spawn_sync(
vte::PtyFlags::DEFAULT,
None,
&[&std::path::PathBuf::from("/usr/bin/fish")],
cwd,
&shell,
&[],
glib::SpawnFlags::DEFAULT,
Some(&mut || {}),
c.as_ref(),
)
.unwrap();
vte.watch_child(pid);
)?;
nb.append_page(&vte, Some(&l));
nb.set_tab_reorderable(&vte, true);
vte.connect_child_exited(clone!(@weak nb, @weak vte => move |_a, status| {
println!("Child exited with status {}", status);
vte.connect_child_exited(clone!(@weak nb, @weak vte => move |a, status| {
println!("Child exited with status {:?} {}", a, status);
let p_num = nb.page_num(&vte);
nb.remove_page(p_num);
}));
@ -49,13 +62,10 @@ pub fn build_tab(nb: &gtk::Notebook, w_accel_group: &gtk::AccelGroup) -> vte::Te
gtk::Inhibit(false)
});
vte.connect_window_title_changed(move |term| {
if let Some(title) = term.get_window_title() {
l.set_label(&title);
} else {
l.set_label("");
}
});
vte.connect_window_title_changed(clone!(@weak nb => move |term| {
set_title(term, &nb);
}));
window.add_accel_group(&new_accel_g);
// Setto colori terminale
use glib::translate::ToGlibPtr;
use std::str::FromStr;
@ -91,7 +101,32 @@ pub fn build_tab(nb: &gtk::Notebook, w_accel_group: &gtk::AccelGroup) -> vte::Te
unsafe_palette.len(),
);
}
vte
Ok(vte)
}
fn set_title(term: &vte::Terminal, nb: &gtk::Notebook) {
let tab_n = if let Some(num) = nb.page_num(term) {
format!("{}. ", num + 1)
} else {
"".to_string()
};
if let Some(l) = nb.get_tab_label(term) {
if let Ok(l) = l.downcast::<gtk::Label>() {
if let Some(title) = term.get_window_title() {
l.set_label(&format!("{}{}", tab_n, title));
} else {
l.set_label(&tab_n);
}
}
}
}
pub fn set_titles(nb: &gtk::Notebook) {
for page_n in 0..nb.get_n_pages() {
if let Some(widget) = nb.get_nth_page(Some(page_n)) {
if let Ok(vte) = widget.downcast::<vte::Terminal>() {
set_title(&vte, nb);
}
}
}
}
pub fn passa_a_tab(win: &gtk::ApplicationWindow, nb: &gtk::Notebook, vte: &vte::Terminal) {
@ -110,15 +145,25 @@ pub fn focus_tab_corrente(nb: &gtk::Notebook) {
}
}
}
fn inject(term: &vte::Terminal, command: String) {
term.feed_child_binary(format!("{}\n", command.trim()).as_bytes());
}
pub fn apri_tab(
window: &gtk::ApplicationWindow,
nb: &gtk::Notebook,
accel_g: &gtk::AccelGroup,
focus: bool,
cwd: Option<String>,
shell: Option<Vec<String>>,
inject_command: Option<String>,
) {
let new_tab = build_tab(&nb, accel_g);
let new_tab = build_tab(window, nb, cwd, shell);
if let Ok(new_tab) = new_tab {
window.show_all();
if focus {
crate::tabs::passa_a_tab(&window, &nb, &new_tab);
}
if let Some(command) = inject_command {
inject(&new_tab, command);
}
}
}

30
src/toggle.rs 100644
View File

@ -0,0 +1,30 @@
#![allow(deprecated)]
extern crate dbus;
#[macro_use]
extern crate dbus_macros;
use dbus::{BusType, Connection};
use std::rc::Rc;
dbus_interface!("net.ddns.chiocciolo.waydrop.term", interface Term {
fn toggle() -> bool;
fn run_shell(cwd: String, shell: Vec<String>) -> bool;
fn run_in_default_shell(cwd: String, command: String) -> bool;
fn run_in_custom_shell(cwd: String , shell: Vec<String>, command: String) -> bool;
});
fn main() {
let session_connection = std::rc::Rc::new(Connection::get_private(BusType::Session).unwrap());
let term = Term::new(
"net.ddns.chiocciolo.waydrop.term",
"/Term",
session_connection,
);
// let res = term.run_in_custom_shell(
// vec!["/bin/bash".to_string()],
// "/usr/bin/htop".to_string(),
// );
//let res = term.run_in_default_shell("/".to_string(), "ls".to_string());
let _ = term.toggle();
}

View File

@ -1,7 +0,0 @@
use std::os::unix::net::UnixStream;
use std::io::prelude::*;
fn main() -> std::io::Result<()>{
let mut s = UnixStream::connect("/tmp/waydrop.sock")?;
s.write_all(b"t")?;
Ok(())
}

View File

@ -1,23 +1,49 @@
use dbus_macros::*;
use glib::Sender;
pub fn listener(tx: &Sender<u32>) {
use std::io::Read;
use std::os::unix::net::UnixListener;
let _a = std::fs::remove_file("/tmp/waydrop.sock");
let sock = UnixListener::bind("/tmp/waydrop.sock").unwrap();
for stream in sock.incoming() {
match stream {
Ok(mut stream) => {
let mut buf = [0u8];
if let Ok(_n) = stream.read_exact(&mut buf) {
let _s = String::from_utf8_lossy(&buf).into_owned();
tx.send(0).expect("can't send");
}
}
Err(err) => {
eprintln!("{:?}", err);
}
}
pub enum RpcCommand {
Toggle,
RunShell {
cwd: Option<String>,
shell: Vec<String>,
},
RunInDefaultShell {
cwd: Option<String>,
command: String,
},
RunInCustomShell {
cwd: Option<String>,
shell: Vec<String>,
command: String,
},
}
dbus_class!("net.ddns.chiocciolo.waydrop.term", class Term (tx: Sender<RpcCommand>) {
fn toggle(&this) -> bool{
this.tx.send(RpcCommand::Toggle).is_ok()
}
fn run_shell(&this, cwd: String, shell: Vec<String>) -> bool {
let cwd = if cwd != "" {Some(cwd)} else {None };
this.tx.send(RpcCommand::RunShell{cwd, shell}).is_ok()
}
fn run_in_default_shell(&this, cwd: String, command: String) -> bool {
let cwd = if cwd != "" {Some(cwd)} else {None };
this.tx.send(RpcCommand::RunInDefaultShell{cwd, command}).is_ok()
}
fn run_in_custom_shell(&this, cwd: String, shell: Vec<String>, command: String) -> bool {
let cwd = if cwd != "" {Some(cwd)} else {None };
this.tx.send(RpcCommand::RunInCustomShell{cwd, shell, command}).is_ok()
}
});
pub fn listener(tx: Sender<RpcCommand>) {
use dbus::{BusType, Connection};
let session_connection = Connection::get_private(BusType::Session).unwrap();
let hello = Term::new(tx);
hello.run(
"net.ddns.chiocciolo.waydrop.term",
&session_connection,
"/Term",
);
}

8
waydrop.desktop 100644
View File

@ -0,0 +1,8 @@
[Desktop Entry]
Name=Waydrop
Exec=/home/pietro/Schifezze/cacca/target/release/waydrop
Icon=
Terminal=false
Type=Application
Categories=GNOME;GTK;System;Utility;TerminalEmulator;