Giter Club home page Giter Club logo

lucky's Introduction

lucky

lucky is an input daemon for Xorg configured with a lua script.

To get a quick overview of what can be done, see the examples.

build

Note: requires Zig master, you can download builds at https://ziglang.org/download

Dependencies:

  • xcb
  • xcb-keysyms

To install, run zig build -p <prefix> where <prefix> is the directory that contains the bin folder you want it to install to.

So to install it to the system you could do:

sudo zig build -p /usr/local

and to install it for just the current user you could do:

zig build -p ~/.local

You may also define a different build mode using -Doptimize=<mode>, the default is ReleaseFast

features

  • Bind press and release functions to keys and mouse buttons
  • Bind motion and window enter and exit functions to mouse buttons
    • motion_resolution option to determine how often to read motion events. Defaults to 5 so motion binds don't overwhelm your system (i.e. every 5th motion event will call the binding's motion callback).
  • Optional filter function to make a binding only active in specific contexts, if the filter returns false the key will be passed through to other applications
  • Various API functions to make complex, contextual bindings possible

cli flags

  • -c, --config - file path to load for the config, defaults to XDG_CONFIG_HOME/lucky/config.lua

api

  • lucky.bind(bind_string, { ... }) - bind a modifier+key/mouse button combination
  • lucky.cmd(command, arg1, arg2, ...) - run a command directly, with function argument being a new argument to the command
  • lucky.shell(command_string) - runs command_string under the system's shell, useful if you want to use subshells, pipelines, file redirects, etc. which are not available when running a command through cmd
  • lucky.is_root(window_id) - returns true if window_id is the root window
  • lucky.get_root() - returns the ID of the root window (based on the currently focused window)
  • lucky.get_parent_window(window_id) - return the ID of the immediate non-root parent of window_id, if no parent exist return window_id
  • lucky.get_top_level_window(window_id) - return the ID of the top level non-root parent of window_id, if no parents exist return window_id
  • lucky.get_focused_window() - return the ID of the currently focused window
  • lucky.get_geometry(window_id) - returns a table containing the x, y, width, height, and border_width of window_id
  • lucky.get_title(window_id) - returns the title of window_id
  • lucky.get_class(window_id) - returns the class of window_id
  • lucky.get_instance(window_id) - returns the instance of window_id
  • lucky.reload() - reload your config

examples

launch a terminal

lucky.bind('super Return', {
    press = function(window_id)
        lucky.cmd(os.getenv('TERMINAL') or 'xterm')
    end
})

bind super 1-9 to switch tag in dwm

for i=1,9 do
    lucky.bind('super ' .. tostring(i), {
        press = function()
            lucky.cmd('dwmc', 'viewex', tostring(i - 1))
        end,
    })
end

bind a key for a specific window

-- when Discord is focused, this keybinding will be active
lucky.bind('alt Return', {
    filter = function(wid)
        return lucky.get_class(wid) == "discord"
    end,
    press = function()
        lucky.cmd('notify-send', 'Discord is the current focused window')
    end
})

-- when Discord is not focused, this keybinding will be active
lucky.bind('alt Return', {
    press = function()
        lucky.cmd('notify-send', 'Discord is NOT the current focused window')
    end
})

reload config

lucky.bind('super minus', {
    press = function(window_id)
        lucky.reload()
    end
})

open clipboard in mpv

lucky.bind('super p', {
    press = function(window_id)
        lucky.shell('mpv --force-window=immediate "$(xclip -o -sel clip)"')
    end
})

horizontal mouse position as a tag switcher when holding super alt mouse_left

function pointer_to_tag(x, y, window_id)
    local max_x = lucky.get_geometry(lucky.get_root()).width - 1
    local percent = x / max_x
    local tag = math.floor(percent * 9) -- 9 tags
    lucky.cmd('dwmc', 'viewex', tostring(tag))
end

lucky.bind("super alt mouse_left", {
    press = pointer_to_tag,
    motion = pointer_to_tag
})

vertical mouse as a volume slider if you press the left mouse button on the left edge of the screen

function volume_slider(x, y, wid)
    local max_y = lucky.get_geometry(lucky.get_root()).height - 1
    local percent = math.floor(((max_y - y) / max_y) * 100)
    lucky.cmd('pactl', 'set-sink-volume', '@DEFAULT_SINK@', tostring(percent) .. '%')
end

lucky.bind("mouse_left", {
    filter = function(x, y, wid)
        return x == 0
    end,

    press = volume_slider,
    motion = volume_slider
})

future plans

  • MAN PAGE!!!!!
  • Pass arbitrary data on startup, so you can load thinsg dynamically in the config
    • For example, you could pass in the window manager for loading wm-specific keybinds, if you use multiple window managers
  • Ability to send arbitrary inputs through the lua API, so keys can be rebound in certain contexts
  • Make key repeat detectable
  • Plan9-esque Mouse chording
    • I already know internally how to implement this, just need to work out the specifics of how it'll work for the user-side of things
  • Expose more information to the binding callbacks, possibly shove it all in a table instead of individual function arguments
    • Mouse position for key presses
    • Mouse positions relative to the window, not just global position
    • Mouse movement relative to the last motion event for motion callback
  • Look into what's possible with the X input extension
    • In particular, I'd like to implement things like touchpad and touchscreen gestures. Maybe stuff with drawing tablet input as well (pressure, for example).
    • I have a general idea of how to do stuff with this but I don't have devices to test with which makes it rather difficult to build support for these things
  • Chording system
    • Could perhaps work by giving a table to a function instead, which has keys to functions or more tables for nested chords
    • Callback users can implement when updating the chord state, they could use this information to build their own whichkey-like system
  • Allow users to replay a matched keybinding to other clients
    • Consider gutting the filter callback if this is implemented, since it lets you effectively do the same thing (the filter function might be a more comfortable for the common use case though, so maybe it'd still be worth keeping)
  • Allow users to implement named labels for bindings. This would allow for things like enabling/disabling bindings via their label, or removing the binding entirely.

lucky's People

Contributors

banchouboo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

lucky's Issues

non-recursive mappings ?

First of all, I do appreciate the work you've put in for lucky, I believe it has great potential.
I would like to map ctrl+w to ctrl+Backspace in Firefox (which I can do right now), but I would like to map ctrl+x to ctrl+w in Firefox, in order to close the current tab. This I cannot do right now, since If I'm doing lucky.cmd('xdotool', 'key', '--clearmodifiers', 'ctrl+w'), then lucky intercepts that, and I'm stuck in an infinite loop. How can I get out of it?

Saw your post on sxhkd.

Hello.

I found lucky from your sxhkd issue post.

It's possible to do this with lucky.

I'm sure you've done a lot of work to get lucky working. I haven't downloaded and installed yet.

Would be fantastic if you could update the main /README.md to include some screenshots (maybe animated .GIF showing the related task in action)

Would also really be nice to see an example added that covers Windows Specific Keybinds.

It might also be helpful for new users if the Examples were the first thing to lead off the README.md to help orient new users to what Lucky can do for them.

Just feedback to try and help support all of your effort.

I'm looking forward to when I have time to download and experiment with lucky.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.