AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Lex' Mouse Gestures
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Lexikos



Joined: 17 Oct 2006
Posts: 2526
Location: Australia, Qld

PostPosted: Fri Nov 23, 2007 5:30 am    Post subject: Lex' Mouse Gestures Reply with quote

Lex' Mouse Gestures
Yet another mouse gestures script! I wrote this one (at least) several months ago, after trying various mouse gesture scripts and applications. For some I did not like the configuration methods, and for others I did not like the way gesture recognition worked.

This script allows gestures similar to the All-in-One Gestures addon for Firefox, since that is what I was used to.

I had been intending to rewrite the script and add more features, but... I'm too lazy. Rolling Eyes

Gestures are triggered by holding the gesture key (default is right mouse button), drawing a sequence of "strokes" (line segments) then releasing the gesture key.

Features:
  • Allows an arbitrary number of directions ("zones"), though 4 is the most practical and efficient.
  • Allows any number of "strokes" in a gesture.
  • Gestures either execute a label or send keystrokes.
  • Wheel gestures (gesture key + wheel up/down.)
  • Various options controlling gesture recognition. See Gestures Default.ahk for more information.
  • Custom normal and suspended tray icons.
  • Win + Gesture key enables/disables gestures, and indicates the current status by playing a sound from Wurt Simplicity.
  • Note that it ignores the length of each stroke (excluding m_LowThreshold and m_HighThreshold), so two consecutive strokes cannot be in the same zone. For instance, Gesture_L_L is not valid, since it would be recognized as Gesture_L.

Script Structure:
    Gestures.ahk contains the "gesture engine," while Gestures Default.ahk contains the default settings and any gestures which are implemented in script (vs pure keystrokes.) Gestures.ini is used to override settings, or define pure keystroke gestures.
    When a gesture is executed, the script builds a label/variable name in the format:
      %c_GesturePrefix%_%zone1%_%zone2%_%zoneN%
    For example:
      Gesture_L_U
    This represents left, then up. c_GesturePrefix is defined in Gestures Default.ahk, and is "Gesture" by default. It could be used by a label-associated gesture to easily switch between a "set" of gestures. (The script doesn't use this capability yet.)
    If a variable exists of the relevant name, the variable's contents are sent as keystrokes.
    If no variable exists, but a label does, the label is executed.

Default Gestures:
    Implemented in Gestures Default.ahk as labels:
    • Gesture_L (left) - Back - !{Left}, ^-, or Browser_Back depending on the active window.
    • Gesture_R (right) - Forward.
    • Gesture_D_R (down, then right) - Close the active window. A three second delay is implemented to allow cancelling by pressing Escape.
    • Gesture_R_D_L_U (right, down, left, up) - Reload the script.
    • Gesture_L_D_R_U (left, down, right, up) - Edit Gestures.ini.
    • Gesture_L_D (left, down) - Minimize active window.
    • Gesture_R_U (right, up) - Maximize active window.
    • Gesture_R_L (right, left) or
      Gesture_L_R (left, right) - Undo recent minimize, restore active window, or restore the "top-most" minimized window.
    • Gesture_L_D_U (left, down, up) or
      Gesture_U_L_D_U (up, left, down, up) - Restore the "top-most" minimized window. (Since the above gesture prefers to restore the active window if maximized.)
    • Gesture_R_L_R_L (right, left, right, left) or
      Gesture_L_R_L_R (left, right, left, right) - Enter "window move" mode. Click or press Enter to confirm window location. Press Escape to cancel. (This really just activates "Move" from the window's system menu.)
    • Gesture_Default - Pressing the gesture key without moving the mouse executes Gesture_Default. If the gesture key is a mouse button, it simulates a click+drag from the gesture start point to the current mouse location, otherwise it sends a keystroke. Gesture_Default is also executed if the gesture is cancelled via m_Timeout and m_DefaultOnTimeout is non-zero.
    Implemented in Gestures.ini as pure keystroke assignments:
    • Gesture_WheelUp (gesture key + wheel up) - Ctrl+Shift+Tab.
    • Gesture_WheelDown (gesture key + wheel down) - Ctrl+Tab.
    • Gesture_L_U (left, up) - Up one level in Explorer/a file dialog.
    • Gesture_U (up) - Launch_App1 (usually My Computer.)
    • Gesture_D (down) - Launch_App2 (usually Calculator.)
    • Gesture_D_U (down, up) - Browser_Home.
    • Gesture_D_L (down, left) - ^F4 (usually close tab/document.)
    • Gesture_D_R_L (down, right, left) - !F4 (close window without delay.)

Download
(Includes script, default ini, tray icons and wurt sounds used by the script.)
Back to top
View user's profile Send private message
Andreone



Joined: 20 Jul 2007
Posts: 257
Location: Paris, France

PostPosted: Fri Nov 23, 2007 10:30 am    Post subject: Reply with quote

This is a really nice script Very Happy and very useful
Thank you
Back to top
View user's profile Send private message
catweazle
Guest





PostPosted: Thu Jan 03, 2008 9:06 pm    Post subject: Reply with quote

Did you consider rendering "mouse trails" on the screen to show the gesture as it's being composed (as per all-in-one gestures)? I think this would be a useful addition.

Some time ago I added very basic trail support (rendering multiple tiny windows) to one of the earlier mouse gesture scripts (see below), although it could probably be improved by rendering lines directly to the screen.


Code:

;
; mg.ahk - Mouse gestures with right button.
;
; Jason Hood, 15 August to 9 September, 2004.
;
; Adapted from mousegesture.ahk from:
;   http://lukewarm.s41.xrea.com/AutoHotkey/myscripts/
;

;#NoTrayIcon
Menu Tray, Tip, Mouse Gestures

SetMouseDelay -1
SetDefaultMouseSpeed 0
mg_active = 0

timeout = 50            ; approx. half a second
sensitivity = 10        ; this many pixels required before being accepted

; Show a tooltip indicating the current gesture; uncomment to hide it.
;mg_showtips = hide
;mg_showtrails = hide
; Ignore unknown gestures (no right click); uncomment to do the click.
;mg_rclick = yes

; Define the recognised gestures (each of these should have an _Action label).
; Any number of directions is allowed, so, for example, an "S" (or "5") gesture
; could be created with "LDRDL".
gestures = -L-R-U-D-UD-DR-RU-DL-DR-LDR-DU-DURD-DLU-

; Window titles to exclude.
excluded = Pixia,Firefox,Virtual Machine Remote Control,Remote Desktop,Potter

; Window titles which automatically disable the gestures (it can't quite handle
; simultaneous left/right presses correctly).
disabled = Minesweeper,Cheat Mine,Potter

; Initialise variables for the actions and exit.
;goto action_init

SetWinDelay,0
CoordMode,Mouse,Screen

; Initialise variables to support mouse pointer trails
trail=50
delay=20
;trans=255
image=C:\4x4_red.bmp

; Create small 4x4 windows to represent mouse pointer trails
Loop,%trail%
{
  Gui,%A_Index%:+Owner +AlwaysOnTop -Resize -SysMenu -MinimizeBox -MaximizeBox +Disabled -Caption -Border -ToolWindow
  Gui,%A_Index%:Margin,0,0
  Gui,%A_Index%:Add,Picture,,%image%
  Gui,%A_Index%:Show,X-50 Y-50 W4 H4 NoActivate,MouseTrail%A_Index%
  ;WinSet,TransColor,FFFFFF %trans%,MouseTrail%A_Index%
  ;trans-=25
}

; Hotkeys for script control.
#g::Suspend
+#g::Reload
^#g::Edit
!#g::ExitApp

;------------------------------------------------------------------------------

DR_Action:
  ; Close the active window.
  WinClose A
  return

DL_Action:
  ; Minimize the active window.
  ; WinMinimize A

;  WinGetClass, GestureInitiatedWindow, ahk_id %winid%
;
;  ;MsgBox, "Active" %GestureInitiatedWindow%
;
;  If GestureInitiatedWindow in Progman
;  {
;;    MsgBox, "Clicked root"
;    If LastMinimized <>
;    {
;      WinRestore
;    }
;  }
;  Else
;  {
;    PostMessage, 0x112, 0xF020,,, A ; 0x112 = WM_SYSCOMMAND, 0xF020 = SC_MINIMIZE
;    LastMinimized = %winid%
;  }

  PostMessage, 0x112, 0xF020,,, A ; 0x112 = WM_SYSCOMMAND, 0xF020 = SC_MINIMIZE
  return

; -----------------------------------------------------------------------------

D_Action:
  WinGetClass, ActiveClass, A
  If ActiveClass in ExploreWClass,CabinetWClass
  {
    ControlGetText, Dir, Edit1, A
   
    ;WinGetTitle, Dir, A
    ;Run, explore %Dir%
    If Dir = My Documents
      Dir = %A_MyDocuments%
    Else If Dir = My Computer
      Dir = %A_MyComputer%
    Else If Dir = Desktop
      Dir = %A_Desktop%
   
    Run, explorer /n `, %Dir%
  }
  return

; -----------------------------------------------------------------------------

U_Action:
  WinGetClass, ActiveClass, A
  If ActiveClass in ExploreWClass,IEFrame,CabinetWClass
  {
    WinGetTitle, Title, A
    Send, {Backspace}
  }
  return

UD_Action:
; Strg+N erzeugt im Explorer oder Dateidialog einen neuen Ordner
~^M:: ; Strg+M (~ = native)
WinGetClass, ActiveClass, A                    ; Klasse des aktiven Fensters
If ActiveClass in ExploreWClass,CabinetWClass  ; Wenn Explorer-Fenster ...
{
  Send, !F
  Send, w
  Send, f
}
IfWinActive, ahk_class #32770                            ; Ist Dateidialog?
{
   PostMessage, 0x111, 40962                                ; Direkten Befehl für neuer Ordner senden
}
return

RU_Action:
  WinGet state, MinMax, A
  If state = 1 ;  maximized (or minimized)
    WinRestore,A
  else ; normal window
  WinMaximize,A
  return

L_Action:
  WinGetClass, ActiveClass, A
  If ActiveClass in ExploreWClass,IEFrame,CabinetWClass,wndclass_desked_gsk
    Send, !{Left}
  return

R_Action:
  WinGetClass, ActiveClass, A
  If ActiveClass in ExploreWClass,IEFrame,CabinetWClass,wndclass_desked_gsk
    Send, !{Right}
  return

LDR_Action:
  Run, C:\
  return

DU_Action:
  if (A_ComputerName = "CATWEAZLE")
    url = http://www.google.co.uk
  else
    url = http://ra/johnc
  Run,%url%
  return

DURD_Action:
  Run,%userprofile%\My Documents
  return

DLU_Action:
  Send, #d
  return


;------------------------------------------------------------------------------

;MButton::
;  mb = M
;goto MouseButton

;LButton::
;  mb = L

;MouseButton:
;    If mg_active = 1
;    {
;        IfEqual mg_showtips,, Tooltip
;            mg_executed = 1
;        mg_str = %mb%B
;        goto %mg_str%_Action
;    }
;    ; I like to use middle button as left double-click.
;    If mb = M
;    {
;        MouseClick L,,, 2
;        return
;    }

; NOTE: This function is needed for excluded windows (e.g., Firefox) to be handled correctly
ButtonWait:
  ;FileAppend mg_active %mg_active% `n, C:\debug.txt
  ;IfEqual,mg_active,0,Return
  MouseClick %mb%,,,,,D
  loop
  {
    GetKeyState st, %mb%Button, P
    IfEqual st, U, break
    Sleep 10
  }
  MouseClick %mb%,,,,,U
  return

;WheelUp::
;  mg_str = WU
;goto Wheel
;
;WheelDown::
;  mg_str = WD
;
;Wheel:
;  If mg_active = 1
;  {
;    IfEqual mg_showtips,, Tooltip
;    mg_executed = 1
;    goto %mg_str%_Action
;  }
;  MouseClick %mg_str%
;return

^+RButton::
  Loop,%trail%
  {
    WinSet,Top,,MouseTrail%index%
  }
  MsgBox, raised gesture windows
  return

;^RButton::
+RButton::
RButton::
;  Loop,%trail%
;  {
;    WinSet,Top,,MouseTrail%index%
;  }

  MouseGetPos,,, id
  WinGetTitle mg_title, ahk_id %id%

  If mg_title contains %disabled%
    Suspend
  else
  {
    If mg_title contains %excluded%
      ;If !GetKeyState("Control")
      If !GetKeyState("LShift")
      {
   mb = R
   goto ButtonWait
      }
    mg_active = 1
    mg_executed = 0
    mg_rheld = 0
    mg_str =
    mg_idletime = 0
    mg_rclick =
    ;IfEqual mg_showtips,, ToolTip %A_Space%
    MouseGetPos px, py, winid
    px2 = %px%
    py2 = %py%
    loop
    {
      GetKeyState sh, Shift, P
      If sh = D
      {
   mg_rclick = yes
   ;MsgBox, shift down
      }

      GetKeyState st, RButton, P
      If st = U ; the button has been released
      {
        IfEqual mg_showtips,, ToolTip
        IfEqual mg_showtrails,, GoSub, ClearTrails
       
        If mg_rheld = 0
        {
          mg_active = 0
          IfEqual mg_showtrails,, GoSub, ClearTrails
          If mg_executed = 0
            If mg_str =
              MouseClick R
          else IfInString gestures, -%mg_str%-
            gosub %mg_str%_Action
          else IfNotEqual mg_rclick,,MouseClick, R
          }
        else IfNotEqual mg_rclick,,MouseClick,R,,,,,U
;      else
;        MouseClick R,,,,,U
          return
        }
      else If mg_idletime < %timeout%
        ; button still pressed, within timeout since last direction change
        {
          MouseGetPos dx, dy
          dx -= %px2%
          dy -= %py2%
          If dx > %sensitivity%
            mg_dir = R
          else If dx < -%sensitivity%
            mg_dir = L
          else If dy > %sensitivity%
            mg_dir = D
          else If dy < -%sensitivity%
            mg_dir = U
          If mg_dir <>
          {
            StringRight,right,mg_str,1
            IfNotInString, right, %mg_dir%
            {
              mg_str = %mg_str%%mg_dir%
            }
            IfEqual mg_showtips,, ToolTip %mg_str%
            MouseGetPos px2, py2
            mg_idletime = 0
            mg_dir =
          }
          else
            mg_idletime++
        }
      else ; timeout has expired
      {
        IfEqual mg_showtips,,ToolTip Gesture Expired
        If mg_rheld = 0
          If mg_executed = 0
          {
            MouseGetPos px2, py2
            If px2 <> %px%
              If py2 <> %py%
              {
                IfEqual mg_showtips,, ToolTip
                IfEqual mg_showtrails,, GoSub, ClearTrails
      If mg_rclick <> 
      {
                  MouseClick R, %px%, %py%,,,D
                  MouseMove %px2%, %py2%
                }
                mg_rheld = 1
                mg_active = 0
              }
          }
      }
     
      If (mg_active)
        IfEqual mg_showtrails,, GoSub, DrawTrails
      Sleep delay
    }
  }
  mb = R
  goto ButtonWait
 

DrawTrails:
  ;FileAppend index %index% trail %trail% `n, C:\debug.txt
  If (index > trail)
  {
    ;FileAppend greater %index% `n, C:\debug.txt
    index = 1
  }
  ;FileAppend index %index% `n, C:\debug.txt
 
  MouseGetPos,x,y
  x+=5
  y+=5
  WinMove,MouseTrail%index%,,%x%,%y%
  index += 1
 
  Return


ClearTrails:
  Loop,%trail%
  {
    WinMove,MouseTrail%A_Index%,,-10,-10
    ;WinSet,Top,,MouseTrail%index%
  }
  Return
Back to top
majkinetor



Joined: 24 May 2006
Posts: 3622
Location: Belgrade

PostPosted: Thu Jan 03, 2008 9:45 pm    Post subject: Reply with quote

Thank you
_________________
Back to top
View user's profile Send private message MSN Messenger
Lexikos



Joined: 17 Oct 2006
Posts: 2526
Location: Australia, Qld

PostPosted: Fri Jan 04, 2008 4:18 am    Post subject: Reply with quote

catweazle wrote:
Did you consider rendering "mouse trails" on the screen to show the gesture as it's being composed (as per all-in-one gestures)? I think this would be a useful addition.
I find trails distracting rather than useful. The tactile response of the mouse is effective enough, IMO. Eventually the movements become so natural you don't need to think about which way you're moving the mouse.
Back to top
View user's profile Send private message
juan
Guest





PostPosted: Sat Jan 26, 2008 8:38 pm    Post subject: Reply with quote

thankyou, really nice script, I´m now using it
I added the current gesture to tooltip for one second, just for a litle feedback

bye
Back to top
juan
Guest





PostPosted: Sat Jan 26, 2008 8:51 pm    Post subject: Reply with quote

I´m a litle newbe to do it my self, what do you think about adding to gestures .ini something like

[mp3 @ C:\.* - xplorer²]
Gesture_D_U = !{F4}

["- Mozilla Firefox"]
Gesture_D_U = {Browser_Home}

[else]
Gesture_D_U = {something_else}

or something better, like using the classname to, it would be great Smile

thanks againg, i´m enjoying your script
and sorry about my english
Back to top
Lexikos



Joined: 17 Oct 2006
Posts: 2526
Location: Australia, Qld

PostPosted: Sun Jan 27, 2008 2:35 am    Post subject: Reply with quote

I've been planning to revise Gestures for a long time, especially for context-sensitive gestures, but since I very rarely edit my gestures, other projects have taken precedence.

Note that you can script any gesture by adding it to either ahk file:
Code:
Gesture_D_U:
    SetTitleMatchMode, RegEx
    ifWinActive, mp3 @ C:\\.* \- xplorer²  ; assuming ".*" was meant as a wildcard
        Send !{F4}
    else ifWinActive, \- Mozilla Firefox ahk_class MozillaUIWindowClass
        Send {Browser_Home}
    else
        Send {Launch_App1}
    return
Be sure to remove Gesture_D_U from your ini file, if present.
Back to top
View user's profile Send private message
Juan
Guest





PostPosted: Sun Jan 27, 2008 4:13 pm    Post subject: Reply with quote

thanks lexikos, that´s the way i´m doing it now, i think your script is very good, if you find the time please revise it a litle, I´ll try for my self, thanks again and see you
Back to top
jpsala



Joined: 21 Jan 2008
Posts: 7

PostPosted: Sun Jan 27, 2008 10:05 pm    Post subject: Reply with quote

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 Smile

Gesture_D = doSomething<win>Scite<=>- SciTE
Gesture_D = doSomethingElse<win>Firefox<=>- Mozilla Firefox


Code:

;
; 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%
}

Code:

; 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! Very Happy

Juan
Back to top
View user's profile Send private message MSN Messenger
automaticman



Joined: 27 Oct 2006
Posts: 320

PostPosted: Fri Feb 22, 2008 12:21 pm    Post subject: Reply with quote

Thanks for sharing. I didn't "download" and try it out yet. As I prefer inputting mostly with the keys I'm not sure if I would use these gestures "often". Then I would have to leave the keyboard and move the mouse. But in contrary it might be useful if I already switched over to the mouse (because I had to) then those gestures might free me from jumping back to the keyboard just to fire some hotkeys.

I don't know how your solution works but interesting would be also having one "multiplication gesture", when triggered, opening a GUI with buttons in it like: DoThis, DoThat, AplicationXDoThis, ApplicationYDoThat which you can press and the GUI disappears again (similar to nDroid's GUI maybe). This would give us a multiplicative operation on gestures using
+ gesture + click on gui
as input mechanism. (Similar to this idea is enterpad here. Our enterpad would be the GUI.)
Maybe I should reactivate my Wacom tablet to try out these gestures.

+ The next step could be a ZUI enterpad, we wouldn't be limited to a given window size. We could zoom in/out into various regions and so have 1000's of hotkey/automation buttons in front of us. Smile
Back to top
View user's profile Send private message
jpsala



Joined: 21 Jan 2008
Posts: 7

PostPosted: Fri Feb 22, 2008 2:35 pm    Post subject: Reply with quote

yep, I like your ideas but don´t have the energy, nor the knowledge of autohotkey to do it, I hope someone can do it.
I don´t use the mouse either, but when surfing and researching the keyboard, with some minor exceptions, like gmail, is useless.
Thanks for the feedback

[ Moderator!: Please do not top-post., ie dont quote the entire previous post unneccessarily. This is not practiced in our forum. ]
Back to top
View user's profile Send private message MSN Messenger
automaticman



Joined: 27 Oct 2006
Posts: 320

PostPosted: Fri Feb 22, 2008 2:40 pm    Post subject: Reply with quote

This package seems not to include gestures for
    copy
    paste
    cut
    delete
    undo
and these are among the most general operations used all over applications.
+ Principle: Increasing it's power by increasing it's quantitative impact.
Back to top
View user's profile Send private message
jpsala



Joined: 21 Jan 2008
Posts: 7

PostPosted: Fri Feb 22, 2008 2:54 pm    Post subject: Reply with quote

no, you can make your own gestures easily, just take a look at the files and the examples and youll be making yours in no time, if you come up with some idea tell me, good luck
Back to top
View user's profile Send private message MSN Messenger
automaticman



Joined: 27 Oct 2006
Posts: 320

PostPosted: Fri Feb 22, 2008 2:58 pm    Post subject: Reply with quote

I would apply gestures more to general operations as written above than "small space operations".
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group