added option for fullscreen window (#12)

* added option for fullscreen window

* added option for fullscreen window

* WIP center & top positions with proper positioning

* Added enum for absolute and fractions for the vertical offset and width

* fixed readme in regards to relative numbers

* Fixed default background color for the main box

---------

Co-authored-by: Kirottu <arnovaara@gmail.com>
This commit is contained in:
Andrej Benz
2023-04-13 13:13:40 +02:00
committed by GitHub
parent e472fe73b1
commit 61773e2d79
3 changed files with 100 additions and 46 deletions

View File

@@ -53,9 +53,12 @@ After that you need to create the configuration file and place it in `~/.config/
```ron
Config(
width: 800,
width: Absolute(800),
position: Top,
vertical_offset: Absolute(0), // How much the runner is shifted vertically
hide_icons: false,
ignore_exclusive_zones: true, // ignore exclusive zones, f.e. Waybar
layer: Overlay, // GTK Layer: Bottom, Top, Background, Overlay
hide_plugin_info: false,
plugins: [
"libapplications.so",
@@ -100,9 +103,12 @@ The config file has the following structure, and as seen in the name uses the `r
```ron
Config(
width: 800, // The width of the window
width: Absolute(800), // The width of the window
position: Top,
vertical_offset: Absolute(0), // How much the runner is shifted vertically
hide_icons: false,
ignore_exclusive_zones: true, // ignore exclusive zones, f.e. Waybar
layer: Overlay, // GTK Layer: Bottom, Top, Background, Overlay
hide_plugin_info: false,
plugins: [
"libapplications.so", // Relative paths are looked up in the <config dir>/plugins/ directory

View File

@@ -1,5 +1,10 @@
#window {
background-color: rgba(0, 0, 0, 0);
}
box#main {
border-radius: 10px;
background-color: @theme_bg_color;
}
list#main {

View File

@@ -8,18 +8,30 @@ use serde::Deserialize;
use wl_clipboard_rs::copy;
#[derive(Deserialize)]
enum Position {
Top,
Center,
struct Config {
width: RelativeNum,
vertical_offset: RelativeNum,
position: Position,
plugins: Vec<PathBuf>,
hide_icons: bool,
hide_plugin_info: bool,
ignore_exclusive_zones: bool,
layer: Layer,
}
#[derive(Deserialize)]
struct Config {
width: u32,
plugins: Vec<PathBuf>,
position: Position,
hide_icons: bool,
hide_plugin_info: bool,
enum Layer {
Background,
Bottom,
Top,
Overlay,
}
// Could have a better name
#[derive(Deserialize)]
enum RelativeNum {
Absolute(i32),
Fraction(f32),
}
/// A "view" of plugin's info and matches
@@ -35,6 +47,12 @@ struct Args {
config_dir: Option<String>,
}
#[derive(Deserialize)]
enum Position {
Top,
Center,
}
/// Actions to run after GTK has finished
enum PostRunAction {
Copy(Vec<u8>),
@@ -169,20 +187,31 @@ fn activate(app: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
let window = gtk::ApplicationWindow::builder()
.application(app)
.name(style_names::WINDOW)
.width_request(config.width as i32)
.build();
// Init GTK layer shell
gtk_layer_shell::init_for_window(&window);
// Anchor based on configured position
match config.position {
Position::Top => gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Top, true),
Position::Center => (),
// Make layer-window fullscreen
gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Top, true);
gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Bottom, true);
gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Left, true);
gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Right, true);
if config.ignore_exclusive_zones {
gtk_layer_shell::set_exclusive_zone(&window, -1);
}
gtk_layer_shell::set_keyboard_mode(&window, gtk_layer_shell::KeyboardMode::Exclusive);
gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Overlay);
match config.layer {
Layer::Background => {
gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Background)
}
Layer::Bottom => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Bottom),
Layer::Top => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Top),
Layer::Overlay => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Overlay),
};
// Try to load custom CSS, if it fails load the default CSS
let provider = gtk::CssProvider::new();
@@ -306,7 +335,6 @@ fn activate(app: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
// Text entry box
let entry = gtk::Entry::builder()
.hexpand(true)
.has_focus(true)
.name(style_names::ENTRY)
.build();
@@ -320,28 +348,9 @@ fn activate(app: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
)
});
let anchor_set = Rc::new(RefCell::new(false));
// Handle other key presses for selection control and all other things that may be needed
let entry_clone = entry.clone();
window.connect_key_press_event(move |window, event| {
// Set margin & anchor properly after the window is already present, otherwise GTK can't figure out the right monitor
if matches!(config.position, Position::Center) && !*anchor_set.borrow() {
let monitor = window
.display()
.monitor_at_window(&window.window().unwrap())
.unwrap();
gtk_layer_shell::set_anchor(window, gtk_layer_shell::Edge::Top, true);
gtk_layer_shell::set_margin(
window,
gtk_layer_shell::Edge::Top,
monitor.geometry().height() / 2 - entry_clone.allocated_height() - 2,
);
*anchor_set.borrow_mut() = true;
}
use gdk::keys::constants;
match event.keyval() {
// Close window on escape
@@ -483,16 +492,50 @@ fn activate(app: &gtk::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
}
});
let main_vbox = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical)
.name(style_names::MAIN)
.build();
main_vbox.add(&entry);
window.add(&main_vbox);
// Show the window initially, so it gets allocated and configured
window.show_all();
// Add and show the list later, to avoid showing empty plugin categories on launch
main_vbox.add(&main_list);
main_list.show();
// Create widgets here for proper positioning
window.connect_configure_event(move |window, event| {
let width = match config.width {
RelativeNum::Absolute(width) => width,
RelativeNum::Fraction(fraction) => (event.size().0 as f32 * fraction) as i32,
};
// The GtkFixed widget is used for absolute positioning of the main box
let fixed = gtk::Fixed::builder().build();
let main_vbox = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical)
.halign(gtk::Align::Center)
.vexpand(false)
.width_request(width)
.name(style_names::MAIN)
.build();
main_vbox.add(&entry);
let vertical_offset = match config.vertical_offset {
RelativeNum::Absolute(offset) => offset,
RelativeNum::Fraction(fraction) => (event.size().1 as f32 * fraction) as i32,
};
fixed.put(
&main_vbox,
(event.size().0 as i32 - width) / 2,
match config.position {
Position::Top => vertical_offset,
Position::Center => {
(event.size().1 as i32 - entry.allocated_height()) / 2 + vertical_offset
}
},
);
window.add(&fixed);
window.show_all();
// Add and show the list later, to avoid showing empty plugin categories on launch
main_vbox.add(&main_list);
main_list.show();
entry.grab_focus(); // Grab the focus so typing is immediately accepted by the entry box
false
});
}
fn handle_matches(