284 lines
9.5 KiB
Rust
284 lines
9.5 KiB
Rust
/* waydrop - a drop-down terminal for wayland
|
|
*
|
|
* Copyright 2021 Pietro Brenna <pietro.brenna@briq.it>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
use gtk::gio;
|
|
use gtk::glib;
|
|
|
|
use gio::prelude::*;
|
|
use gtk::prelude::*;
|
|
|
|
use glib::clone;
|
|
// use gtk4::SettingsExt;
|
|
use std::env::args;
|
|
use std::thread;
|
|
|
|
mod menu;
|
|
mod tabs;
|
|
mod wake_listener;
|
|
mod window_state;
|
|
use crate::vte::TerminalExt;
|
|
use window_state::{FullScreenState, StateOperations, WindowPos, WindowState};
|
|
|
|
fn build_ui(application: >k::Application) {
|
|
let window = gtk::ApplicationWindow::new(application);
|
|
window.settings().set_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(Some("Waydrop"));
|
|
// window.border().set_left(0);ò
|
|
let surf = window.surface();
|
|
// 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, 700);
|
|
window.set_decorated(false);
|
|
|
|
window.set_can_focus(true);
|
|
window.set_keep_above(true);
|
|
let nb = gtk::Notebook::new();
|
|
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_show_border(false);
|
|
let accel_group = gtk::AccelGroup::new();
|
|
let (key, modifier) = gtk::accelerator_parse("<Control><Shift>t");
|
|
accel_group.connect_accel_group(
|
|
key,
|
|
modifier,
|
|
gtk::AccelFlags::VISIBLE,
|
|
clone!(@weak window, @weak nb => @default-return true, move |_accel_g, _window, _key, _modif| {
|
|
tabs::open_tab(&window, &nb, true, None, None, None, &w_state6);
|
|
true
|
|
}),
|
|
);
|
|
let a = gtk::accelerator_parse("<Control>Page_Down");
|
|
let b = gtk::accelerator_parse("<Alt>plus");
|
|
for (key, modifier) in &[a, b] {
|
|
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 a = gtk::accelerator_parse("<Control>Page_Up");
|
|
let b = gtk::accelerator_parse("<Alt>egrave");
|
|
for (key, modifier) in &[a, b] {
|
|
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("<Control><Shift>c");
|
|
accel_group.connect_accel_group(
|
|
key,
|
|
modifier,
|
|
gtk::AccelFlags::VISIBLE,
|
|
clone!(@weak nb => @default-return true, move |_accel_g, _window, _key, _modif| {
|
|
let p_num = nb.get_current_page();
|
|
let page = nb.get_nth_page(p_num);
|
|
if let Some(vte) = page {
|
|
let _ = vte.downcast::<vte::Terminal>().map(|x| if x.get_has_selection() {
|
|
x.emit_copy_clipboard()
|
|
});
|
|
}
|
|
true
|
|
}),
|
|
);
|
|
|
|
let (key, modifier) = gtk::accelerator_parse("<Control><Shift>v");
|
|
accel_group.connect_accel_group(
|
|
key,
|
|
modifier,
|
|
gtk::AccelFlags::VISIBLE,
|
|
clone!(@weak nb => @default-return true, move |_accel_g, _window, _key, _modif| {
|
|
let p_num = nb.get_current_page();
|
|
let page = nb.get_nth_page(p_num);
|
|
if let Some(vte) = page {
|
|
let _ = vte.downcast::<vte::Terminal>().map(|x| x.paste_clipboard());
|
|
}
|
|
true
|
|
}),
|
|
);
|
|
let (key, modifier) = gtk::accelerator_parse("F11");
|
|
accel_group.connect_accel_group(
|
|
key,
|
|
modifier,
|
|
gtk::AccelFlags::VISIBLE,
|
|
clone!(@weak window => @default-return true, move |_accel_g, _win, _key, _modif| {
|
|
match w_state4.get_full() {
|
|
FullScreenState::Full => {
|
|
window.unfullscreen();
|
|
w_state4.set_full(FullScreenState::NotFull);
|
|
}
|
|
FullScreenState::NotFull => {
|
|
window.fullscreen();
|
|
w_state4.set_full(FullScreenState::Full);
|
|
}
|
|
_ => {}
|
|
}
|
|
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);
|
|
if let Ok(first_tab) = tabs::build_tab(&nb, None, None, &w_state5) {
|
|
tabs::go_to_tab(&window, &nb, &first_tab);
|
|
}
|
|
window.set_skip_taskbar_hint(true);
|
|
window.set_skip_pager_hint(true);
|
|
window.show_all();
|
|
window.hide();
|
|
/*unsafe {
|
|
gdk_sys::gdk_window_set_skip_pager_hint(
|
|
window.get_window().unwrap().to_glib_none().0,
|
|
true.to_glib(),
|
|
);
|
|
gdk_sys::gdk_window_set_skip_taskbar_hint(
|
|
window.get_window().unwrap().to_glib_none().0,
|
|
true.to_glib(),
|
|
);
|
|
}*/
|
|
|
|
window.connect_focus_out_event(move |_widget, _b| window_state::focus_out(&w_state1));
|
|
window.connect_focus_in_event(clone!(@weak window => @default-return gtk::Inhibit(false),
|
|
move |_widget, _b| window_state::focus_in(&window, &w_state2)));
|
|
nb.connect_destroy(move |_nb| {
|
|
w_state.set_pos(WindowPos::Closing);
|
|
});
|
|
nb.connect_page_removed(clone!(@weak window => move |notebook, _vte, _index| {
|
|
if notebook.get_n_pages() == 0 {
|
|
if w_state0.get_pos() != WindowPos::Closing {
|
|
crate::tabs::open_tab(&window, ¬ebook, false,None, None, None, &w_state5);
|
|
window_state::hide(&window, &w_state0);
|
|
}
|
|
} else {
|
|
tabs::set_titles(¬ebook);
|
|
if notebook.get_n_pages() == 1 {
|
|
notebook.set_show_tabs(true);
|
|
}
|
|
}
|
|
}));
|
|
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(¬ebook);
|
|
});
|
|
|
|
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
|
//window_state::bring_up(&window, &w_state4, gtk::get_current_event_time());
|
|
//tabs::focus_tab_corrente(&nb);
|
|
rx.attach(None, move |cmd| {
|
|
let tira_su = || {
|
|
window_state::bring_up(&window, &w_state3, gtk4::get_current_event_time());
|
|
};
|
|
use wake_listener::RpcCommand::*;
|
|
match cmd {
|
|
Toggle => {
|
|
window_state::esegui_toggle(&window, &nb, &w_state3);
|
|
}
|
|
NewShell { cwd } => {
|
|
tira_su();
|
|
tabs::open_tab(&window, &nb, true, cwd, None, None, &w_state7);
|
|
}
|
|
RunShell { cwd, shell } => {
|
|
tira_su();
|
|
tabs::open_tab(&window, &nb, true, cwd, Some(shell), None, &w_state7);
|
|
}
|
|
RunInDefaultShell { cwd, command } => {
|
|
tira_su();
|
|
tabs::open_tab(&window, &nb, true, cwd, None, Some(command), &w_state7);
|
|
}
|
|
RunInCustomShell {
|
|
cwd,
|
|
shell,
|
|
command,
|
|
} => {
|
|
tira_su();
|
|
tabs::open_tab(&window, &nb, true, cwd, Some(shell), Some(command), &w_state7);
|
|
}
|
|
}
|
|
glib::Continue(true)
|
|
});
|
|
thread::spawn(move || {
|
|
if let Err(e) = wake_listener::listener(tx) {
|
|
eprintln!("Could not listen on dbus: {}", e);
|
|
}
|
|
});
|
|
}
|
|
|
|
fn main() {
|
|
let application =
|
|
gtk::Application::new(Some("net.ddns.chiocciolo.waydrop"), Default::default())
|
|
.expect("Initialization failed...");
|
|
|
|
application.connect_activate(|app| {
|
|
build_ui(app);
|
|
});
|
|
application.run(&args().collect::<Vec<_>>());
|
|
}
|