Logitech G15 modifier keys

Posted by Ked on Mon 01 Dec 2008 02:42 AM — 3 posts, 21,991 views.

Russia #0
This is for those of us who happen to own a Logitech G15 keyboard.

I've always found the default behaviour of the G keys to be rather limited, since there are only 18 of them, so you have to move your hand back and forth between the main qwerty set of keys and the macro one all the time. So instead, I use G keys as modifiers for the numpad. This gives me a much greater number of macros and lets me group commands according to the type of action.

For example, I can move in several different ways: leap, walk, sprint, fly. By assigning each method of movement to a G key (G13 for leaping, G14 for flying, etc) I can switch movement methods with those keys, while still using the numpad for actually moving around.

Previously, getting this to work involved some tedious and ugly hacking in G15's macro editor but the 2nd version of the firmware introduced Lua scripting, which makes this much simpler and more flexible.

All you have to do to set this up on the keyboard's side is copy/paste the following snippet into Logitech's script editor for your Mushclient profile:


function OnEvent(event, arg)
	--OutputLogMessage("event = %s, arg = %s\n", event, arg);
    if event == "G_PRESSED" then
        PressKey(0x1d, 0x38)
        PressAndReleaseKey("a")
        ReleaseKey(0x1d, 0x38)
        local m,g = tostring(GetMKeyState()), tostring(arg)
        PressAndReleaseKey("m", m, "k")
        string.gsub(g, "(%d)", function(mt) PressAndReleaseKey(mt) end)
        PressAndReleaseKey("enter")
        PressKey(0x1d, 0x38)
    elseif event == "G_RELEASED" then
        ReleaseKey(0x1d, 0x38)
        local m,g = tostring(GetMKeyState()), tostring(arg)
        PressAndReleaseKey("e", m, "k")
        string.gsub(g, "(%d)", function(mt) PressAndReleaseKey(mt) end)
        PressAndReleaseKey("enter")
        PressKey(0x1d, 0x38)
        PressAndReleaseKey("z")
        ReleaseKey(0x1d, 0x38)
    end
end


Save it and assign "Script" to all the G keys in the profile.

On Mushclient's side you need to install the plugin below and edit the modifier rule tables, as explained in the plugin's description.
Russia #1
Plugin:


<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<muclient>
<plugin
   name="Keyboard"
   author="Keldar"
   id="3c3ef7503f44b4b76d89c99e"
   language="Lua"
   purpose="Logitech G15 macros"
   save_state="y"
   date_written="2008-11-30"
   requires="4.00"
   version="1.0"
   >
   
<description trim="y">
<![CDATA[
Commands:

  bind keys       -  bind all G modifiers
  unbind keys     -  unbind all G modifiers

Notes:
  
Replace the 'modes' table with your own. The 
keys in this table are strings describing G
modifiers, of the form "m#k#", where "m#" stands
for the M mode selected and "k#" - number of the
pressed G key. 

Values are tables keyed by strings describing 
numpad keys with values holding alias strings to
be executed when the corresponding numpad key is 
pressed.

To combine G modifiers together, concatenate their
labels with "+", placing them in the resulting 
string in ascending order wrt the G key's number.
For  example, to make G7 and G8 to work as a single 
modifier in M1 you'd use the string "m1k7+m1k8". 
The table containing rules for multiple modifiers 
is "multi_modes". It contains an example rule for 
G1+G2.

There are no limits on the number of G keys used
together in a single modifier, though 2 or 3 are 
probably the physically usable maximum. You should
also not mix M modes in multiple modifiers, meaning
that "m1k1+m2k2" isn't guaranteed to work.
]]>
</description>
</plugin>


<aliases>
  <alias
   script="BindKeys"
   match="^\s*bind\s+keys\s*$"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
  <alias
   script="UnbindKeys"
   match="^\s*unbind\s+keys\s*$"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
</aliases>
<aliases>
  <alias
   script="pressG15"
   match="^g15start$"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
</aliases>
<aliases>
  <alias
   script="releaseG15"
   match="^g15end$"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
</aliases>
<aliases>
  <alias
   script="BoundCall"
   match="^(NUM.)$"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
</aliases>
<!--  Script  -->


<script>
<![CDATA[

modes = {

m1k7 = {
    desc = "Axethrow",
    ["NUM8"]   = "thn",
    ["NUM9"]   = "thne",
    ["NUM7"]   = "thnw",
    ["NUM4"]   = "thw",
    ["NUM6"]   = "the",
    ["NUM1"]   = "thsw",
    ["NUM2"]   = "ths",
    ["NUM3"]   = "thse",
    ["NUM-"]   = "thup",
    ["NUM+"]   = "thd",
    ["NUM/"]   = "thi",
    ["NUM*"]   = "tho",
    ["NUM5"]   = "thp"
},
}

multi_modes = {

["m1k1+m1k2"] = {
    desc = "Test",
    ["NUM7"]         = "cl nw",
    ["NUM8"]         = "cl n",
    ["NUM9"]         = "cl ne",
    ["NUM4"]         = "cl w",
    ["NUM6"]         = "cl e",
    ["NUM1"]         = "cl sw",
    ["NUM2"]         = "cl s",
    ["NUM3"]         = "cl se",
    ["NUM/"]         = "cl in",
    ["NUM*"]         = "cl out",
    ["NUM-"]         = "cl up",
    ["NUM+"]         = "cl down",
    ["NUM5"]         = "rl",
},

}



keypad = {
  ["Divide"]             = "NUM/",
  ["Multiply"]           = "NUM*",
  ["Subtract"]           = "NUM-",
  ["Add"]                = "NUM+",
  ["Numpad7"]            = "NUM7",
  ["Numpad8"]            = "NUM8",
  ["Numpad9"]            = "NUM9",
  ["Numpad4"]            = "NUM4",
  ["Numpad5"]            = "NUM5",
  ["Numpad6"]            = "NUM6",
  ["Numpad1"]            = "NUM1",
  ["Numpad2"]            = "NUM2",
  ["Numpad3"]            = "NUM3",
  ["Numpad0"]            = "NUM0",
  ["Decimal"]            = "NUM."
}

function BindKeys()
    AcceleratorTo("Ctrl+Alt+a", "", 0)
    AcceleratorTo("Ctrl+Alt+a", "g15start", sendto.execute)
    AcceleratorTo("Ctrl+Alt+z", "g15end", sendto.execute)

  	for k,v in pairs(keypad) do
  		AcceleratorTo("Ctrl+Alt+" .. k, "", 0)
		AcceleratorTo("Ctrl+Alt+" .. k, v, sendto.execute) 
  	end
  	print("All keybindings set.")
end

function UnbindKeys()
    AcceleratorTo("Ctrl+Alt+a", "", 0)
    AcceleratorTo("Ctrl+Alt+z", "", 0)
  	for k,v in pairs(keypad) do
  		AcceleratorTo("Ctrl+Alt+" .. k, "", 0)
  	end
    print("All keybindings cleared.")
end

input = ""
state = {}
state.pressed = 0

function saveInput()
    if state.pressed == 1 then
        SelectCommand()
        input = PasteCommand("")    
        OnPluginCommandEntered = opce
    end
end

function restoreInput()
    if state.pressed == 0 then
        SelectCommand()
        PasteCommand(input)
        OnPluginCommandEntered = opceNull
    end
end


function pressG15()
    state.pressed = state.pressed + 1
    saveInput()
end

function releaseG15()
    state.pressed = state.pressed - 1
    restoreInput()
end

function g15command(wildcs)
    if wildcs[2] == "m" then
        state[wildcs[1]] = true
    elseif wildcs[2] == "e" then
        state["m" .. wildcs[3] .. "k" .. wildcs[4]] = nil
    end
end

function modString()
    local t = {}
    for k,_ in pairs(state) do
        if k ~= "pressed" then
            table.insert(t, k)
        end
    end
    local sorter = function(a,b) 
        local sa,ea,ka = string.find(a, "^m%dk(%d+)$")
        local sb,eb,kb = string.find(b, "^m%dk(%d+)$")
        if sa and sb then
            return tonumber(ka) < tonumber(kb)
        end
    end
    table.sort(t,sorter)
    return t
end

function BoundCall(name, outp,wildcs)
    local mods = table.concat(modString(), "+")
    if state.pressed > 1 then
        if multi_modes[mods] then
            Execute(multi_modes[mods][wildcs[0]])
        end
    else
        if modes[mods] then
            Execute(modes[mods][wildcs[0]])
        end
    end
end

function clearInput()
    SelectCommand()
    PushCommand("")
end

function opce(stxt)
    local s,e,w1,w2,w3,w4 = string.find(stxt, "^(([me])([1-3])k(%d+))")
    if s then g15command({w1,w2,w3,w4}) end
    clearInput()
    return "\t"
end

function opceNull(stxt)
    return stxt
end

OnPluginCommandEntered = opceNull

BindKeys()
]]>
</script>

</muclient>
Amended on Mon 01 Dec 2008 02:49 AM by Ked
Australia Forum Administrator #2
Lua scripting on the G15? Wow!