Crate le_petit_lapin
source ·Expand description
Copyright (c) 2023 Gabriel G. de Brito
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Le Petit Lapin - The cute X window manager.
Le Petit Lapin is a X window manager written in Rust as a library. One must
create a binary Cargo crate that depends on lapin
to build it with a desired
configuration.
The name “Le petit lapin” was choosen by a friend of mine and it means “The little bunny” in French, but I’m not 100% sure about that because I don’t speak French.
This is the official API and code documentation. Check out config examples and snippets in the wiki, on the source repository.
To use this crate you’ll need both XCB and Xlib installed.
Quickstart
To use Lapin is to write your own window manager in Rust, depending on this crate. The most minimal config looks like this:
use le_petit_lapin::keys::*;
use le_petit_lapin::layouts::*;
use le_petit_lapin::*;
use std::env;
#[rustfmt::skip]
fn main() {
// First, we connect to the X server and creates a window
// manager object.
let mut lapin = Lapin::connect();
// The best way to set the modkey and other things you'll use
// later is assigning constants.
const MODKEY: &str = "Super";
const TERMINAL: &str = "alacritty";
// Keybinds are handled in a separate object, here we create
// it and bind keys. The macro lazy! is used to create a
// callback closure.
let mut keybinds = KeybindSet::new();
keybinds.bindall(vec![
// workspace keys
(&[MODKEY], "1", lazy! {wm, wm.goto_workspace(0)}),
(&[MODKEY], "2", lazy! {wm, wm.goto_workspace(1)}),
(&[MODKEY], "3", lazy! {wm, wm.goto_workspace(2)}),
(&[MODKEY], "4", lazy! {wm, wm.goto_workspace(3)}),
(&[MODKEY], "5", lazy! {wm, wm.goto_workspace(4)}),
(&[MODKEY], "6", lazy! {wm, wm.goto_workspace(5)}),
(&[MODKEY], "7", lazy! {wm, wm.goto_workspace(6)}),
(&[MODKEY], "8", lazy! {wm, wm.goto_workspace(7)}),
(&[MODKEY], "9", lazy! {wm, wm.goto_workspace(8)}),
(&[MODKEY, "Shift"], "1", lazy! {wm, wm.send_window_to_workspace(0)}),
(&[MODKEY, "Shift"], "2", lazy! {wm, wm.send_window_to_workspace(1)}),
(&[MODKEY, "Shift"], "3", lazy! {wm, wm.send_window_to_workspace(2)}),
(&[MODKEY, "Shift"], "4", lazy! {wm, wm.send_window_to_workspace(3)}),
(&[MODKEY, "Shift"], "5", lazy! {wm, wm.send_window_to_workspace(4)}),
(&[MODKEY, "Shift"], "6", lazy! {wm, wm.send_window_to_workspace(5)}),
(&[MODKEY, "Shift"], "7", lazy! {wm, wm.send_window_to_workspace(6)}),
(&[MODKEY, "Shift"], "8", lazy! {wm, wm.send_window_to_workspace(7)}),
(&[MODKEY, "Shift"], "9", lazy! {wm, wm.send_window_to_workspace(8)}),
// quit
(&[MODKEY], "q", lazy! {Lapin::quit()}),
// spawns
(&[MODKEY], "Return", lazy! {Lapin::spawn(TERMINAL)}),
(&[MODKEY], "n", lazy! {Lapin::spawn("chromium")}),
(&[MODKEY], "a", lazy! {Lapin::spawn("rofi -show run")}),
// kill focus
(&[MODKEY], "w", lazy! {wm, wm.killfocused()}),
// change focus
(&[MODKEY], "j", lazy! {wm, wm.nextwin()}),
(&[MODKEY], "k", lazy! {wm, wm.prevwin()}),
// change layout
(&[MODKEY], "space", lazy! {wm, wm.next_layout()}),
(&[MODKEY, "Shift"], "space", lazy! {wm, wm.prev_layout()}),
// swap slaves
(&[MODKEY, "Shift"], "k", lazy! {wm, wm.swap_with_prev_slave()}),
(&[MODKEY, "Shift"], "j", lazy! {wm, wm.swap_with_next_slave()}),
// change master
(&[MODKEY, "Shift"], "Return", lazy! {wm, wm.change_master()}),
// toggle ool
(&[MODKEY, "Shift"], "t", lazy! {wm, wm.toggle_ool()}),
// fullscreen
(&[MODKEY, "Shift"], "f", lazy! {wm, wm.fullscreen()}),
// change focused screen (monitor)
(&[MODKEY], "y", lazy! {wm, wm.prev_screen()}),
(&[MODKEY], "u", lazy! {wm, wm.next_screen()}),
// change focused window screen
(&[MODKEY, "Shift"], "y", lazy! {wm, wm.send_window_to_prev_screen()}),
(&[MODKEY, "Shift"], "u", lazy! {wm, wm.send_window_to_next_screen()}),
//
// Check all callbacks usefull for keybinds in the the docs
// for the Lapin struct
//
]);
// The modkey used to move and resize floating windows.
lapin.config.mouse_mod = &[MODKEY];
// The three default layouts.
let tile = Tiling::new();
let max = Maximized::new();
let float = Floating::new();
lapin.config.layouts = layouts![tile, max, float];
//
// Check all config options in docs for the Config struct.
//
// We can assign a closure to be called right after everything
// is setup.
let mut callback = lazy! {{
let home = env!("HOME");
Lapin::spawn("picom");
Lapin::spawn(&format!("feh --no-fehbg --bg-fill {home}/.config/wallpaper"));
}};
// The last thing to do is init the window manager object with
// the keybinds and the callback.
lapin.init(&mut keybinds, Some(&mut callback));
}
Modules
- General configuration of the window manager.
- Keybind system
- This module defines a bunch of useful public functions to the
Lapin
struct. Check then on docs forLapin
. - Default layouts for the window manager and a trait to create new ones.
- Rule system for Lapin.
Macros
- Creates a Vec of layouts suitable for use with the window manager.
- Creates a closure suitable to use in keybinds.
- Macro to easily create rules
Structs
- Atoms struct for the window manager.
- The window manager I suppose.