Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions anyrun/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ pub struct Config {
#[config_args(skip)]
#[serde(default = "Config::default_keybinds")]
pub keybinds: Vec<Keybind>,

#[config_args(skip)]
#[serde(default = "Config::default_mousebinds")]
pub mousebinds: Vec<Mousebind>,
}
impl Config {
fn default_x() -> RelativeNum {
Expand Down Expand Up @@ -103,6 +107,19 @@ impl Config {
},
]
}

fn default_mousebinds() -> Vec<Mousebind> {
vec![
Mousebind {
button: MouseButton::Primary,
action: Action::Select,
},
Mousebind {
button: MouseButton::Secondary,
action: Action::Nop,
},
]
}
}
impl Default for Config {
fn default() -> Self {
Expand All @@ -121,6 +138,7 @@ impl Default for Config {
layer: Self::default_layer(),
keyboard_mode: Self::default_keyboard_mode(),
keybinds: Self::default_keybinds(),
mousebinds: Self::default_mousebinds(),
}
}
}
Expand Down Expand Up @@ -173,6 +191,21 @@ pub enum Action {
Select,
Up,
Down,
Nop,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point of having a Nop action?

}

#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
pub enum MouseButton {
Primary,
Secondary,
Middle,
Unknown(u32),
}

#[derive(Deserialize, Debug, Clone, Copy)]
pub struct Mousebind {
pub button: MouseButton,
pub action: Action,
}

#[derive(Deserialize, Clone)]
Expand Down
44 changes: 43 additions & 1 deletion anyrun/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use relm4::prelude::*;
use wl_clipboard_rs::copy;

use crate::{
config::{Action, Config, ConfigArgs, Keybind},
config::{Action, Config, ConfigArgs, Keybind, Mousebind},
plugin_box::{PluginBox, PluginBoxInput, PluginBoxOutput, PluginMatch},
};

Expand Down Expand Up @@ -106,6 +106,27 @@ impl App {
(i, plugin, plugin_match)
})
}

fn select_row(&self, plugin_ind: DynamicIndex, match_ind: DynamicIndex) {
// Select match row
for (i, plugin) in self.plugins.iter().enumerate() {
if i == plugin_ind.current_index() {
for (j, plugin_match) in plugin.matches.iter().enumerate() {
if j == match_ind.current_index() {
plugin
.matches
.widget()
.select_row(Option::<&gtk::ListBoxRow>::Some(&plugin_match.row));
}
}
} else {
plugin
.matches
.widget()
.select_row(Option::<&gtk::ListBoxRow>::None);
}
}
}
}

#[relm4::component]
Expand Down Expand Up @@ -377,6 +398,7 @@ impl Component for App {
}
}
AppMsg::Action(action) => match action {
Action::Nop => {}
Action::Close => {
root.close();
relm4::main_application().quit();
Expand Down Expand Up @@ -472,6 +494,26 @@ impl Component for App {
}
}
}
AppMsg::PluginOutput(PluginBoxOutput::MouseAction(button, match_ind, plugin_ind)) => {
// Handle binding
if let Some(Mousebind { action, .. }) = self
.config
.mousebinds
.iter()
.find(|mousebind| mousebind.button == button)
{
// Potentially select row
match action {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of preprocessing of actions feels a bit ugly, I'd prefer if there was a general enum for mouse actions/events as a part of AppMsg, so that the mouse bindings could be extended to be the way close on click works is that it's just a mouse binding. And maybe deprecating that option as well.

In practice the mouse action part of AppMsg would contain all the different kinds of mouse actions/events that different callbacks will produce, and then the handler for the mouse actions specifically can do the required preprocessing before sending another action, if necessary/applicable.

Action::Select | Action::Nop => self.select_row(plugin_ind, match_ind),
_ => {
// Don't select row for other actions
}
};

// Perform action
sender.input(AppMsg::Action(*action));
}
}
}
self.update_view(widgets, sender);
}
Expand Down
46 changes: 38 additions & 8 deletions anyrun/src/plugin_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,46 @@ use gtk::{glib, pango, prelude::*};
use gtk4 as gtk;
use relm4::prelude::*;

use crate::Config;
use crate::{config::MouseButton, Config};

pub struct PluginMatch {
pub content: Match,
pub row: gtk::ListBoxRow,
config: Rc<Config>,
}

#[derive(Debug)]
pub enum MatchOutput {
MouseAction(MouseButton, <PluginMatch as FactoryComponent>::Index),
}

#[relm4::factory(pub)]
impl FactoryComponent for PluginMatch {
type Init = (Match, Rc<Config>);
type Input = ();
type Output = ();
type Output = MatchOutput;
type CommandOutput = ();
type ParentWidget = gtk::ListBox;
view! {
gtk::ListBoxRow {
set_css_classes: &["match"],
set_height_request: 32,
gtk::Box {

add_controller = gtk::GestureClick {
set_button: 0,
connect_pressed[sender, index] => move |gesture, _, _, _| {
gesture.set_state(gtk::EventSequenceState::Claimed);
let button: MouseButton = match gesture.current_button() {
gtk::gdk::BUTTON_PRIMARY => MouseButton::Primary,
gtk::gdk::BUTTON_SECONDARY => MouseButton::Secondary,
gtk::gdk::BUTTON_MIDDLE => MouseButton::Middle,
other => MouseButton::Unknown(other),
};
sender.output(MatchOutput::MouseAction(button, index.clone())).unwrap();
}
},

set_orientation: gtk::Orientation::Horizontal,
set_spacing: 10,
set_css_classes: &["match"],
Expand Down Expand Up @@ -74,10 +94,10 @@ impl FactoryComponent for PluginMatch {

fn init_widgets(
&mut self,
_index: &Self::Index,
index: &Self::Index,
root: Self::Root,
_returned_widget: &<Self::ParentWidget as relm4::factory::FactoryView>::ReturnedWidget,
_sender: FactorySender<Self>,
sender: FactorySender<Self>,
) -> Self::Widgets {
let widgets = view_output!();

Expand Down Expand Up @@ -140,6 +160,11 @@ pub enum PluginBoxInput {
pub enum PluginBoxOutput {
MatchesLoaded,
RowSelected(<PluginBox as FactoryComponent>::Index),
MouseAction(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is complex enough where it could be structified in the enum, as in:

MouseAction {
    button: MouseButton,
    ...
}

MouseButton,
<PluginMatch as FactoryComponent>::Index,
<PluginBox as FactoryComponent>::Index,
),
}

#[relm4::factory(pub)]
Expand Down Expand Up @@ -212,12 +237,17 @@ impl FactoryComponent for PluginBox {

fn init_model(
(plugin, config): Self::Init,
_index: &Self::Index,
_sender: FactorySender<Self>,
index: &Self::Index,
sender: FactorySender<Self>,
) -> Self {
let matches = FactoryVecDeque::builder()
let ind = index.clone();
let matches = FactoryVecDeque::<PluginMatch>::builder()
.launch(gtk::ListBox::default())
.detach();
.forward(sender.output_sender(), move |output| match output {
MatchOutput::MouseAction(button, row) => {
PluginBoxOutput::MouseAction(button, row, ind.clone())
}
});

Self {
plugin,
Expand Down
41 changes: 26 additions & 15 deletions examples/config.ron
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Config(
// Position/size fields use an enum for the value, it can be either:
// Absolute(n): The absolute value in pixels
// Fraction(n): A fraction of the width or height of the full screen (depends on exclusive zones and the settings related to them) window respectively

// The horizontal position, adjusted so that Relative(0.5) always centers the runner
x: Fraction(0.5),

Expand All @@ -15,18 +15,18 @@ Config(
// The minimum height of the runner, the runner will expand to fit all the entries
// NOTE: If this is set to 0, the window will never shrink after being expanded
height: Absolute(1),

// Hide match and plugin info icons
hide_icons: false,

// ignore exclusive zones, f.e. Waybar
ignore_exclusive_zones: false,
// Hide match and plugin info icons
hide_icons: false,

// ignore exclusive zones, f.e. Waybar
ignore_exclusive_zones: false,

// Layer shell layer: Background, Bottom, Top, Overlay
layer: Overlay,

// Layer shell layer: Background, Bottom, Top, Overlay
layer: Overlay,

// Hide the plugin info panel
hide_plugin_info: false,
hide_plugin_info: false,

// Close window when a click outside the main box is received
close_on_click: false,
Expand All @@ -36,7 +36,7 @@ Config(

// Limit amount of entries shown in total
max_entries: None,

// List of plugins to be loaded by default, can be specified with a relative path to be loaded from the
// `<anyrun config dir>/plugins` directory or with an absolute path to just load the file the path points to.
//
Expand All @@ -52,19 +52,30 @@ Config(
keybinds: [
Keybind(
key: "Return",
action: Select,
action: Select,
),
Keybind(
key: "Up",
action: Up,
action: Up,
),
Keybind(
key: "Down",
action: Down,
action: Down,
),
Keybind(
key: "Escape",
action: Close,
action: Close,
),
],

mousebinds: [
Mousebind(
button: Primary,
action: Select,
),
Mousebind(
button: Secondary,
action: Nop,
),
],
)
46 changes: 46 additions & 0 deletions nix/modules/home-manager.nix
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ in
"select"
"up"
"down"
"nop"
];
};
};
Expand All @@ -232,6 +233,34 @@ in
default = null;
};

mousebinds = mkOption {
type = nullOr (
listOf (submodule {
options = {
button = mkOption {
type = str;
description = ''
Mouse button name

Primary/Secondary/Middle or Unknown(<u32>) with key code for the mouse button.
'';
};
action = mkOption {
type = enum [
"close"
"select"
"up"
"down"
"nop"
];
};
};
})
);
default = null;
};


extraLines = mkOption {
type = nullOr lines;
default = null;
Expand Down Expand Up @@ -328,6 +357,22 @@ in
'') cfg.config.keybinds
}],
'';

mousebinds =
if cfg.config.mousebinds == null then
""
else
''
mousebinds: [
${
concatMapStringsSep "\n" (x: ''
Mousebind(
button: ${capitalize x.button},
action: ${capitalize x.action},
),
'') cfg.config.mousebinds
}],
'';
in
{
assertions = [
Expand Down Expand Up @@ -382,6 +427,7 @@ in
plugins: ${toJSON parsedPlugins},
${optionalString (cfg.config.extraLines != null) cfg.config.extraLines}
${keybinds}
${mousebinds}
)
'';
}
Expand Down