Mouse App Shortcuts

@rebind / mouse-app-shortcutsv0.1.5Public

Side buttons mean back and forward in browsers, undo and redo in editors, previous and next sheet in spreadsheets.

Files

Older release. Installs get 0.1.5.

main.luau2.2 KB

-- Mouse App Shortcuts: Mouse4 and Mouse5 change meaning by focused app.
-- Anywhere not listed, the buttons pass through untouched.

local IS_MAC = _REBIND.platform == "macos"

local cfg = UI.Schema({
  browsers = UI.Text("chrome, firefox, brave, edge, safari, arc", {
    label = "Browsers (back / forward)",
    placeholder = "process names, comma separated",
    tab = "Apps",
  }),
  editors = UI.Text("code, cursor, sublime, notepad++, zed, textedit", {
    label = "Editors (undo / redo)",
    placeholder = "process names, comma separated",
    tab = "Apps",
  }),
  sheets = UI.Text("excel, numbers, soffice, libreoffice", {
    label = "Spreadsheets (previous / next sheet)",
    placeholder = "process names, comma separated",
    tab = "Apps",
  }),
  swap = UI.Toggle(false, {
    label = "Swap the two side buttons",
    tab = "Apps",
  }),
})

-- chords per class: { Mouse4, Mouse5 }
local CHORDS = {
  browsers = if IS_MAC
    then { "LWin+[", "LWin+]" }
    else { "LAlt+Left", "LAlt+Right" },
  editors = if IS_MAC
    then { "LWin+Z", "LWin+LShift+Z" }
    else { "LCtrl+Z", "LCtrl+Y" },
  sheets = if IS_MAC
    then { "LAlt+Left", "LAlt+Right" }
    else { "LCtrl+PageUp", "LCtrl+PageDown" },
}

local function names(list)
  local out = {}
  for name in list:gmatch("[^,]+") do
    name = name:gsub("^%s+", ""):gsub("%s+$", ""):lower()
    if name ~= "" then
      table.insert(out, name)
    end
  end
  return out
end

local function classOf(process)
  process = process:lower()
  for _, class in { "browsers", "editors", "sheets" } do
    for _, name in names(cfg[class]) do
      if process:find(name, 1, true) then
        return class
      end
    end
  end
  return nil
end

local function bindSide(button, index)
  Bind(button, {
    when = function()
      return classOf(System.Window().process) ~= nil
    end,
    action = function()
      local class = classOf(System.Window().process)
      local slot = if cfg.swap then 3 - index else index
      HID.Combo(CHORDS[class][slot])
      return nil
    end,
  })
end

bindSide("Mouse4", 1)
bindSide("Mouse5", 2)

function OnStart()
  Log.Info(
    "Mouse4 and Mouse5 follow the focused app. Elsewhere they pass through."
  )
end

3 files, 3.8 KB.