Hi lexikos, I made some modifications, if you find some time have a look and make the necesary conrrections, take a look at gestures.ini
now you can have the same hotkey for diferent windows
Gesture_D = doSomething<win>Scite<=>- SciTE
Gesture_D = doSomethingElse<win>Firefox<=>- Mozilla Firefox
;
; AutoHotkey Version: 1.0.46.09 +
; Language: English
; Platform: Win XP, 2003, Vista, and probably 2000
; Author: Steve Gray, aka Lexikos
;
; Script Function:
; Mouse gestures.
; - Allows abitrary number of directions (zones).
; - Allows any number of movements/strokes in a sequence.
; - Custom script (label) execution OR variable-based key-stroke simulation.
; - Variable-based key-strokes and options can be set via Gestures.ini
; (setting a variable-based gesture overrides any associated labels/custom scripts)
;
gosub Gestures_Default_Init
; guardo los nombres de las variables
RunDebugView()
; Read gesture definitions from Gestures.ini
G_LoadGestures( A_ScriptDir . "\Gestures.ini" )
; save the name of the gestures in vars
vars := getVars()
c_PI := 3.141592653589793
c_halfPI := 1.5707963267948965 ; Pi/2
c_Degrees := 57.29578 ; 180/Pi (degrees per radian)
#NoEnv
SendMode Input
#SingleInstance force
#KeyHistory 20
CoordMode, Mouse, Screen
SetTitleMatchMode, 2
; custom tray icon (also called by ToggleGestureSuspend)
G_SetTrayIcon(true)
; Hook "Suspend Hotkeys" messages to update the tray icon.
; Note: This has the odd side-effect of "disabling" the tray menu
; if the script is paused from the tray menu.
OnMessage(0x111, "WM_COMMAND")
Menu, TRAY, Tip, Mouse Gestures
Menu, TRAY, Add
Menu, TRAY, Add, Edit &Gestures, EditGestures
Menu, TRAY, Add, Edit &Default Gestures, EditGestures2
Menu, TRAY, Add, Edit &this script, EditThisScript
; RAlt or %m_GestureKey%, whichever was used last
m_LastGestureKey := m_GestureKey
; m_Stroke%i% will be set to the actual strokes (starting at m_Stroke1)
m_StrokeCount = 0
m_WaitForRelease := false
m_PassKeyUp := false
m_ClosingWindow := 0
; Use code similar to this to disable gestures on a per-application basis:
; GroupAdd, Blacklist, Firefox ahk_class MozillaUIWindowClass
; Hotkey, IfWinNotActive, ahk_group Blacklist
; register the hotkey
Hotkey, %m_GestureKey%, GestureKey_Down
Hotkey, #%m_GestureKey%, ToggleGestureSuspend
; extra key
if ( m_GestureKey2 && m_GestureKey2 != m_GestureKey )
{
Hotkey, %m_GestureKey2%, GestureKey_Down
Hotkey, #%m_GestureKey2%, ToggleGestureSuspend
}
if !m_GestureKey2
m_GestureKey2 := m_GestureKey
; see also: GestureKey_Down for GetKeyState(...)
GroupAdd, WinCloseGroup, ahk_class ConsoleWindowClass
GroupAdd, WinCloseGroup, ahk_class AutoHotkey
return
Gestures_Default_Init:
#Include %A_ScriptDir%\Gestures Default.ahk
return
EditGestures:
Run, C:\tools\wscite\SciTE.exe "%A_ScriptDir%\Gestures.ini",, UseErrorLevel
if ErrorLevel = ERROR
Run, C:\tools\wscite\SciTE.exe "%A_ScriptDir%\Gestures.ini"
return
EditGestures2:
Run, C:\tools\wscite\SciTE.exe "%A_ScriptDir%\Gestures Default.ahk",, UseErrorLevel
if ErrorLevel = ERROR
Run, C:\tools\wscite\SciTE.exe "%A_ScriptDir%\Gestures Default.ahk"
return
EditThisScript:
Run, C:\tools\wscite\SciTE.exe %A_ScriptFullPath%,, UseErrorLevel
if ErrorLevel = ERROR
Run, C:\tools\wscite\SciTE.exe "%A_ScriptDir%\Gestures Default.ahk"
return
; Wheel Gestures: Gesture key + Wheel sends keystrokes as defined by
; Gesture_WheelUp and Gesture_WheelDown in Gestures.ini.
WheelUp::
WheelDown::
gesture := c_GesturePrefix ? c_GesturePrefix : "Gesture"
if (m_WaitForRelease && %gesture%_%A_ThisHotkey%)
{ ; holding gesture button && this wheel gesture has a defined action
m_ScrolledWheel := true
m_ExitLoop := true
Send % %gesture%_%A_ThisHotkey%
} else
Send {%A_ThisHotkey%}
return
/********** XBUTTON HOTKEYS - included in the script for (my) convenience.
*/
XButton2 & LButton::MinimizeActiveWindow() ;WinMinimize, A
XButton2 & RButton::
ifWinActive, ahk_group WinCloseGroup
WinClose, A
else
Send !{F4}
return
; Task-switch with XButton1( + Wheel).
XButton1 & WheelUp::AltTab
XButton1 & WheelDown::ShiftAltTab
XButton1::Send !{Tab}
; Document/tab-switch with XButton2( + Wheel)
XButton2 & WheelUp::Send ^+{tab}
XButton2 & WheelDown::Send ^{tab}
XButton2::Send ^{Tab}
MinimizeActiveWindow()
{
global
lastMinTime := A_TickCount
lastMinID := WinExist("A")
; unlike WinMinimize, using WM_SYSCOMMAND, SC_MINIMIZE
; causes the system-wide "Minimize" sound to be played
PostMessage, 0x112, 0xF020
}
; Press Win + Gesture button to enable/disable gestures.
ToggleGestureSuspend:
Suspend, Toggle
G_SetTrayIcon(!A_IsSuspended)
; wurt from: http://addons.miranda-im.org/details.php?action=viewfile&id=1512
if A_IsSuspended
SoundPlay, %A_ScriptDir%\wurt_disabled.wav
else
SoundPlay, %A_ScriptDir%\wurt_enabled.wav
return
; Press Escape to cancel the current gesture (before releasing the gesture button.)
CancelGesture:
Hotkey, Escape, CancelGesture, Off
m_ExitLoop := true
return
GestureKey_Up:
m_WaitForRelease := false
Hotkey, IfWinActive
Hotkey, *%m_LastGestureKey% Up, GestureKey_Up, Off
Hotkey, Escape, CancelGesture, Off
; record for later use
MouseGetPos, m_EndX, m_EndY
if ( m_PassKeyUp )
{
Send {%m_LastGestureKey% Up}
m_PassKeyUp := false
}
return
GestureKey_Down:
if ( !GetKeyState(m_GestureKey, "P") && !GetKeyState(m_GestureKey2, "P") )
return
if ( m_WaitForRelease )
return
m_WaitForRelease := true
m_ExitLoop := false
Hotkey, IfWinActive
m_LastGestureKey := A_ThisHotkey
Hotkey, *%m_LastGestureKey% Up, GestureKey_Up, On
Hotkey, Escape, CancelGesture, On
waitCounter := 0
startX := -1
startY := -1
totalDistance := 0
zone := 0
lastZone := -1
m_StrokeCount := 0
; get starting mouse position
MouseGetPos, lastX, lastY
; record for later use
m_StartX := lastX
m_StartY := lastY
Loop
{
; wait for mouse to move
Sleep, m_Interval
if ( m_ExitLoop )
{
if m_ScrolledWheel
KeyWait, %m_LastGestureKey%
return
}
; increment waitCounter by timer interval
; (may not be entirely accurate if the script is lagging...)
waitCounter += m_Interval
if ( !m_StrokeCount && m_InitialTimeout && waitCounter > m_InitialTimeout )
{
if ( GetKeyState(m_LastGestureKey, "P") )
{
if m_LastGestureKey in LButton,MButton,RButton
{
; convert key name to a "button" (silly how MouseClick won't accept "LButton")
StringLeft, btn, m_LastGestureKey, 1
; remember position
MouseGetPos, m_EndX, m_EndY
; move to point where gesture started, then click
MouseClick, %btn%, m_StartX, m_StartY, , 0, D
; move back into place
MouseMove, m_EndX, m_EndY, 0
btn =
}
else
{
Send {%m_LastGestureKey%}
}
; pass GestureKey Up on to active window
m_PassKeyUp := true
}
return
}
if ( !GetKeyState(m_GestureKey, "P") && !GetKeyState(m_GestureKey2, "P") )
{ ; use location mouse was released at
x := m_EndX
y := m_EndY
}
else ; get current mouse position
MouseGetPos, x, y
offsetX := x - lastX
offsetY := y - lastY
; check if mouse has moved
if ( offsetX!=0 || offsetY!=0 )
{
; calculate distance and angle from previous position
distance := G_GetLength(offsetX, offsetY)
if ( distance > m_LowThreshold )
{
angle := G_GetAngle(offsetX, offsetY)
angle *= c_Degrees
lastX := x
lastY := y
; get zone of angle
if ( m_StrokeCount > 0 || m_InitialZoneCount < 2 )
zone := G_GetZone(angle, m_ZoneCount)
else
zone := G_GetZone(angle, m_InitialZoneCount)
if ( zone == -1 )
{
;DEBUG
;MsgBox, 64, DEBUG, Gesture stroke went off-course! (Exceeded zone tolerance `%%m_Tolerance%.), 5
SoundPlay, *-1
return
}
if ( lastZone != zone )
{
totalDistance := distance
; add stroke zone to the pseudo-array
++m_StrokeCount
m_Stroke%m_StrokeCount% := zone
lastZone := zone
; reset timeout counter
waitCounter := 0
}
else
{
totalDistance += distance
}
if ( m_HighThreshold > 0 && totalDistance > m_HighThreshold )
{
;DEBUG
;MsgBox, 64, DEBUG, Gesture stroke exceeded maximum stroke length: %totalDistance% / %m_HighThreshold%., 5
SoundPlay, *-1
Sleep, 150
SoundPlay, *-1
return
}
}
}
; end loop when gesture key is released
if ( !GetKeyState(m_GestureKey, "P") && !GetKeyState(m_GestureKey2, "P") )
break
}
; cancel gesture if the mouse was immobile for too long after the last gesture
if ( m_Timeout > 0 && waitCounter > m_Timeout )
{
;DEBUG
SoundPlay, *-1
;MsgBox, 64, DEBUG, Gesture timeout- %waitCounter% / %m_Timeout%, 5
if ( m_DefaultOnTimeout )
{
gesture = Gesture_Default
if ( %gesture% )
SendEvent % %gesture%
else if ( IsLabel(gesture) )
gosub %gesture%
}
return
}
gesture := c_GesturePrefix ? c_GesturePrefix : "Gesture"
Loop %m_StrokeCount%
{
; get the zone of this stroke
zone := m_Stroke%A_Index%
; get descriptive label for zone, if possible
if ( A_Index == 1 && m_InitialZoneCount >= 2 )
zoneText := c_Zone%m_InitialZoneCount%_%zone%
else
zoneText := c_Zone%m_ZoneCount%_%zone%
gesture .= "_"
if ( zoneText )
gesture .= zoneText
else
gesture .= zone
}
if ( m_StrokeCount == 0 )
gesture = Gesture_Default
; if gesture points to a variable, send its contents as keystrokes
wins := getWins(gesture . "_ID_", vars)
if (wins <> "")
{
nWin := 0
Loop, Parse, wins, ß
{
if ( SubStr(A_LoopField,1, StrLen(gesture)) == gesture)
{
;gesture := substr(A_LoopField,1,instr(A_LoopField,"_ID_")-1)
sid := substr(A_LoopField,instr(A_LoopField,"_ID_")+4,instr(A_LoopField,"[")-instr(A_LoopField,"_ID_")-4)
win := substr(A_LoopField,InStr(A_LoopField,"<=>")+4,500)
comando := substr(A_LoopField,instr(A_LoopField,"]: ")+3,instr(A_LoopField,"<win>")-instr(A_LoopField,"]: ")-3)
nWin += 1
SetTitleMatchMode, 2
outputdebug, x%win%x
if (WinActive(win))
{
ToolTip %gesture% ID %sid% inWin %win%
SetTimer, RemoveToolTip, 2500
send, %comando%
exit
}
}
}
ToolTip, No %gesture% in any of your %nWin% window definitions
SetTimer, RemoveToolTip, 1500
exit
}
;Gesture_D_ID_a[42 of 63]: comandoScite<win>a<=>ahk_class SciTEWindow
;Gesture_D_ID_b[53 of 63]: comandoFirefox<win>b<=>ahk_class MozillaUIWindowClass
else if ( %gesture% )
{
StringReplace, comando, %gesture%, <win>, Ì
StringSplit, command, comando, Ì, %A_Space%%A_Tab%
if (command0 == 2)
{
SetTitleMatchMode, regex
if WinActive( command2 )
Send % %command1%
Else
gesture := gesture . " no window " . command2
}
else
Send % %gesture%
} ; else if gesture has a label (e.g Gesture_D_R = down, then right), go to it
else if ( IsLabel(gesture) )
{
gosub %gesture%
}
else
gesture := gesture . " no existe"
; MsgBox, , , Unknown gesture with %m_StrokeCount% strokes:`n %gesture%, 2
if (gesture<>"Gesture_Default")
{
ToolTip %gesture%
SetTimer, RemoveToolTip, 1500
}
return
; get angle of {x,y} from positive x-axis, relative to {0,0}
; return value is in RADIANS
G_GetAngle( x, y )
{
global c_PI, c_halfPI
; if {0,0}, angle can be any real value
if ( x==0 && y==0 )
return 0
if ( x > 0 )
{
if ( y >= 0 )
return ATan(y/x)
;y < 0
return ATan(y/x) + 2*c_PI
}
else if ( x < 0 )
{
return ATan(y/x) + c_PI
}
else ; x == 0
{
if ( y > 0 )
return c_halfPI
;y < 0
return -c_halfPI
}
}
; get distance of {x,y} from {0,0}
G_GetLength( x, y )
{
return Sqrt(x*x + y*y)
}
; get the zone of an angle
; angle: specified in degrees
; zoneCount: number of zones (zone centers are at (360/zoneCount) degree intervals)
G_GetZone( angle, zoneCount )
{
local degPerZone
local zone
local tolerance
if ( zoneCount < 2 )
{ ; show debug error message
MsgBox, 16, ERROR, Invalid zoneCount (%zoneCount%) passed to G_GetZone()., 5
return 0
}
if ( angle < 0 ) {
Loop { ; while ( angle < 0 ) would be nice...
angle += 360
if ( angle >= 0 )
break
}
}
; calculate zone size
degPerZone := 360 / zoneCount
; calculate zone - Round() finds the nearest zone (nearest integer)
zone := Mod( Round(angle/degPerZone), zoneCount )
; calculate maximum tolerance
tolerance := degPerZone/2.0
; calculate real tolerance from user-defined tolerance (percentage)
if ( m_Tolerance < 100 )
tolerance *= Abs(m_Tolerance)/100.0
if ( zone == 0 && angle > 180 )
angle -= 360
; return -1 if angle is not within tolerance of the nearest zone
if ( Abs(angle-(zone*degPerZone)) >= tolerance )
zone := -1
return zone
}
G_LoadGestures( filename )
{
; declaring one or more local variables forces newly created variables to be global in scope
local line, varname
; declare a local array (0=array length, 1=first item)
local lineParts0
; these must be explicitly declared local
; (as of AHK 1.0.46.10, StringSplit creates them as local variables either way
; because lineParts0 is local, but references to 'lineParts1' in script refer
; to GLOBAL variables...)
local lineParts1, lineParts2
Loop, Read, %filename%
{
; ignore comments
StringLeft, line, A_LoopReadLine, 1
if ( line = ";" )
continue
; replace " = " with uncommon delimiter
StringReplace, line, A_LoopReadLine, %A_Space%=%A_Space%,
; split the string into (hopefully) two parts: variable, keys to send
StringSplit, lineParts, line, , %A_Space%%A_Tab%
if ( lineParts0 == 2 )
{ ; first search for a window ( <win> )
StringReplace, comando, lineParts2, <win>, Ì
StringSplit, command, comando, Ì, %A_Space%%A_Tab%
if (command0 == 2)
{ ; if there´s one, separate the id and the window
StringReplace, comando, command2, <=>, Ì
StringSplit, command, comando, Ì, %A_Space%%A_Tab%
%lineParts1%_ID_%command1% := lineParts2
%lineParts1%%_ID_%WIN := command2
}
else
{
if ( StrLen(lineParts1) > 0 )
{
; allow underscores by removing them from comparison
StringReplace, varname, lineParts1, _, , All
; check if variable name is alphanumeric
if varname is alnum
%lineParts1% := lineParts2
}
else
{
MsgBox empty variable name on line %A_Index%
}
}
}
}
}
WM_COMMAND(wParam, lParam)
{
static IsPaused, IsSuspended
Critical
id := wParam & 0xFFFF
if id in 65305,65404,65306,65403
{ ; "Suspend Hotkeys" or "Pause Script"
if id in 65306,65403 ; pause
IsPaused := ! IsPaused
else ; at this point, A_IsSuspended has not yet been toggled.
IsSuspended := ! A_IsSuspended
G_SetTrayIcon(!(IsPaused or IsSuspended))
}
}
G_SetTrayIcon(is_enabled)
{
icon := is_enabled ? "gestures.ico" : "nogestures.ico"
icon = %A_ScriptDir%\%icon%
; avoid an error message if the icon doesn't exist
IfExist, %icon%
Menu, TRAY, Icon, %icon%,, 1
}
RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
return
getVars() {
DetectHiddenWindows, On
IfEqual Section,, SetEnv Section, Key
HidWin := WinExist(A_ScriptFullPath " - AutoHotkey v")
OldPar := DllCall("GetParent", UInt,HidWin)
GUI +LastFound
DllCall("SetParent", UInt,HidWin, UInt,WinExist("ahk_class Shell_TrayWnd"))
WinMenuSelectItem ahk_id %HidWin%,,View, Variables
Sleep 0
ControlGetText str, Edit1, ahk_id %HidWin%
WinHide ahk_id %HidWin%
DllCall("SetParent", UInt,HidWin, UInt,OldPar)
Out1 := ""
Loop, Parse, str, `n, `r
{
if SubStr(A_LoopField, 1, 8) == "Gesture_"
Out1 .= A_LoopField . "ß"
}
Return Out1
}
getWins(var, vars)
{
out := ""
Loop, Parse, vars, ß
{
if ( SubStr(A_LoopField,1, StrLen(var)) == var)
out := out . A_LoopField . "ß"
}
return out
}
RunDebugView(){
debuggerpath .= "c:\programme\autohotkey\DebugView\Dbgview.exe"
debuggerTitel := "DebugView on \\" . A_ComputerName . " (local)"
IfExist, %debuggerpath%
ifwinNotexist, %debuggerTitel%
Run, %debuggerpath%
}
; Syntax:
; %c_GesturePrefix%_%zone1%_%zone2%_%zoneN% = keys (in Send-compatible format)
Gesture_WheelUp = ^+{Tab}
Gesture_WheelDown = ^{Tab}
Gesture_L_U = !{Up}
Gesture_D_U = {Browser_Home}
Gesture_DR_R = !{g}
Gesture_D_R = ^{F4}
Gesture_D_R_L = !{F4}
Gesture_L_DR = {Browser_Back}
Gesture_D_UR = ^{End}
Gesture_U_DR = ^{Home}
Gesture_U_UR = #c
Gesture_D = comandoScite<win>Scite<=>- SciTE
; with this text; ahk_class SciTEWindow, instead of the title doesnt work, y tried with regex too. Maibe you can see what is wrong
Gesture_D = comandoFirefox<win>Firefox<=>- Mozilla Firefox
; Override Options specified in "Gestures Default.ahk"
m_GestureKey = RButton
m_GestureKey2 =
Thanks a lot!
Juan