 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
rodfell
Joined: 05 Oct 2007 Posts: 138 Location: Bundaberg (Bundy), Qld, Australia
|
Posted: Tue Nov 06, 2007 12:18 pm Post subject: Simple Mouse Gesture and Rocker |
|
|
Simple Mouse Gesture and Rocker
Latest version is posted here.
Simple Mouse Gesture and Rocker calls subroutines based on either gestures made when the right(r), middle(m), 4th(x1) or fifth(x2) mouse button is held down; when a rocking action is made using these mouse buttons, or a combination of the two.
The script tracks up (u) down (d) left (l) right (r). There is a tolerance of +/- 35 degrees, so it is quite simple and accurate
Subroutines will be called if labelled with the following syntax:
"m-" is the prefix (m for macro)
the next letter is the mouse button that starts the gesture eg m-r: is a gesture that starts with a right click
If the first mouse button (say RButton) remains down and a different mouse button (say LButton) is pressed, the second button is added. eg m-rl:
If a gesture is made, say up then right (ur), the gesture is enclosed in parentheses eg m-r(ur):
gestures and rocking can be combined eg m-rl(u):
Modifier keys - alt(!), ctrl(^) and shift(+) can be used eg m-^r: or m-!-wheeldown:
for simplicity and accuracy, right click-gesture-left click is the same as right click-left click-gesture
With wheel movements, -wheelup or -wheeldown is appended - eg m-r(u)-wheelup:
If the wheel is used, no further gesturing or rocking is allowed (to avoid movement errors). wheel movements can be repeated while the mouse button is held down
Another thing that isn't allowed is gesturing solely with the LButton (so as not to interfere with mouse dragging). The LButton however is registered when other mouse buttons or the mouse wheel are pressed eg m-rl(u): ; m-l-wheelup:
Middle button clicking is difficult if combined with mouse wheel movements. If one is used the other is blocked.This protection can be turned off by making line 3 "wheelguard:=false"
When rocking, the last button clicked can be repeadedly clicked while the other buttons are kept down. also, A different button can be called
eg m-rl can be changed to m-rm or m-rx or if the right button is kept down
You can rock with more than 2 buttons at a time eg m-rlx
By not allowing diagonals, gestures can be drawn without abrupt angles. eg a circle drawn from the top and clockwise is registered as m-r(rdlu): (right down left up)
if a right mouse button gesture is down (d) and right (r), like an "L", a subroutine called m-r(dr): (for gesture with right mouse button, tracking down then right) will be called
the script also pays attention to the window under the gesture and notes if the gesture is made over the desktop
Thanks for any ideas gathered from other gesture programs, especially lexicos
| Code: | demomode:=true ;demonstration mode on/off. change to false when ready to use
mintrack=20 ;minimum length of registered track sector in pixels
wheelguard:=true ;if true, wheel and middle button click can't both be used in the same gesture (recommended)
#MaxHotkeysPerInterval 500 ;prevents problems with rapid wheel movements
winget,windesktop,id,ahk_class Progman ;desktop id, useful for some macros
gosub cleanup
*mbutton:: ;list any mouse buttons that can be uniquely named by first letter here eg. *mbutton is "m"
*lbutton:: ;the asterisk allows for the use of modifier keys
*rbutton::
*xbutton1::
*xbutton2::
lastdown:=thishotkey()
if macrorunning or wheel
return
if not buttonsdown
{
mousegetpos xpos1,ypos1,win1 ;win1 is the window underneath the current gesture
modifier:=(getkeystate("alt","p") ? "!" : "") . (getkeystate("shift","p") ? "+" : "") . (getkeystate("ctrl","p") ? "^" : "")
settimer,tracking,1
}
mouseclick:=buttonsdown.=(not buttonsdown and getkeystate("lbutton","p") ? "l" : "") . lastdown
winget,winactive,id,A ;active window id, useful for some macros
sendinput {lbutton up} ;prevents drag box appearing when left/right rocking and gesturing eg. m-lr(d):
hotkey,*lbutton,on ;*lbutton only tracked when other mouse buttons start tracking
hotkey,*lbutton up,on
return
*mbutton up::
if wheel and wheelguard ;middle button clicks ignored when using wheel (if wheelguard=true)
return
*rbutton up::
*lbutton up::
*xbutton1 up::
*xbutton2 up::
lastup:=thishotkey()
stringreplace,buttonsdown,buttonsdown,%lastup%,,all
buttonsup:=true
settimer,tracking,off ;no more gesture tracking once a mouse button has been released
if not wheel and (lastdown=lastup)
gosub callmacro
if not buttonsdown
gosub cleanup
return
*wheelup::
*wheeldown::
if (instr(buttonsdown,"m") and wheelguard) or macrorunning ;prevents accidental use of mousewheel with middle button gestures
return
if not buttonsdown and getkeystate("lbutton","p")
{
mouseclick:=buttonsdown:="l"
hotkey,*lbutton up,on
}
if (buttonsdown and not buttonsup) or modifier
{
stringtrimleft,wheel,a_thishotkey,1
settimer,tracking,off ;no more tracking once wheel used
goto callmacro
}
stringtrimleft,thishotkey,a_thishotkey,1
if not buttonsdown
sendinput {%thishotkey%}
return
callmacro:
macrorunning:=true
macro:="m-" . modifier . mouseclick . (tracking ? "(" . tracking . ")" : "") . (wheel ? "-" . wheel : "")
if (demomode and macro<>"m-r" and macro<>"m-m")
msgbox,,DEMO MODE,%macro% ,1
else
if islabel(macro)
gosub %macro%
macrorunning:=false
return
cleanup:
if (win1<>windesktop)
win2:=win1 ; used in some gestures, win2 is the window the previous macro acted on
hotkey,*lbutton,off ; restore normal left mouse button function
hotkey,*lbutton up,off
wheel:="",tracking="",buttonsup="",buttonsdown="",mouseclick="",track2="",modifier=""
return
tracking:
mousegetpos xpos2,ypos2
angle:=abs((xpos1-xpos2)/(ypos1-ypos2+0.001)) ;+0.001 avoids divide by zero error
if (angle>0.7 and angle<1.428) or (abs(ypos1-ypos2)<5 and abs(xpos1-xpos2)<5) ;ignores angles within 10 degrees of 45 degree diagonal
return ;ignores movement that is too slow
track1:=(abs(ypos1-ypos2)>abs(xpos1-xpos2)) ? (ypos1>ypos2 ? "u" : "d") : (xpos1>xpos2 ? "l" : "r") ;determines up down left right
if (track1<>track2) ;remembers mouse position when track direction changes
xpos_tack:=xpos2,ypos_tack:=ypos2
if (track1<>SubStr(tracking, 0, 1)) and (track1=track2) and (abs(xpos_tack-xpos2)>=mintrack or abs(ypos_tack-ypos2)>=mintrack)
tracking.=track1 ;track if x or y changing sufficient to register. track needs confirmation (2 tracks same direction)
xpos1:=xpos2,ypos1:=ypos2,track2:=track1
return
thishotkey() ;eg reduces "xbutton1 up" to "x1"
{
stringreplace,thishotkey,a_thishotkey,*,,all
stringreplace,thishotkey,thishotkey,%a_space%up,,all
stringreplace,thishotkey,thishotkey,button,,all
return thishotkey
}
esc::exitapp
m-r: ;normal right click
sendinput {rbutton}
return
m-m: ;normal middle click (optional)
sendinput {mbutton}
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; Examples ;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;; wheel examples ;;;;;;;;;;
m-r-wheelup: ;change volume with wheel - hold right button down and use wheel
Send {Volume_Up}
return
m-r-wheeldown:
Send {Volume_Down}
return
;;;;;;;; rocker examples ;;;;;;;;;;
m-rl:
msgbox,,,if you keep right held down, clicking left will repeat action,5
return
m-lr:
msgbox,,,rocker left then right.,5 ;left click will also fire so some macros not suitable
return ;can be used for browser forward if you don't click over hypertext
m-rl(l):
m-lr(l):
msgbox,,,you combined rocking and gesturing,5
return
;;;;;;;;;;;; gesture examples ;;;;;;;;;;
m-r(u): ;; gesture up ;; maximize window under cursor. maximize last window if cursor over desktop
if (win1=windesktop)
{
if (win2<>"")
winmaximize, ahk_id %win2%
}
else
winmaximize ahk_id %win1%
return
m-r(d): ;minimize window under cursor
if (win1<>windesktop) ;don't minimize the desktop
winminimize, ahk_id %win1%
return
m-r(l): ;browser back
winactivate ahk_id %win1%
sendinput {Browser_Back}
return
m-r(r): ;browser forward
winactivate ahk_id %win1%
sendinput {Browser_Forward}
return
m-r(dr): ;restore last window.
winrestore ahk_id %win2%
return
m-r(ldr): ;close window under cursor (draw a C)
if (win1<>windesktop)
winclose ahk_id %win1%
return |
Last edited by rodfell on Wed May 11, 2011 11:25 am; edited 119 times in total |
|
| Back to top |
|
 |
ManaUser
Joined: 24 May 2007 Posts: 1121
|
Posted: Tue Nov 06, 2007 9:24 pm Post subject: |
|
|
Nice! It's simple and easy to use, but quite serviceable.
I made a slight change to your script though (hope you don't mind). Instead of using five variables, it just adds progressively adds letters to one. This way it can handle any number of strokes, and it actually simplifies the code a bit (no more loops). I added a new six-stroke gesture, M, as an example.
| Code: | ;this script tracks up (u) down (d) left (l) and right (r). There is a tolerance of +/- 45 degrees, so it is quite simple and accurate
;gestures can have curves. eg a circle drawn from the top and clockwise is registered as rdlu (right down left up)
;if a gesture is down (d) and right (r), like an "L", a subroutine called gdr ( for gesture down right) will be called
;if anything is labelled as gdr:, the action will be run
;as a further example, if an "S" is drawn (from top to bottom), gldrdl: (gesture left down right down left) will be called
;these 2 examples are included, as is "M" (U R D U R D)
CoordMode, Mouse, Screen
rbutton::
mousegetpos,xpos1, ypos1
gesture= ;clear previous tracking results, variable array gesture1 to gesture5
settimer, gesture, 10
return
rbutton up::
settimer, gesture, off
gesture := "g" . gesture ;eg. gdr = gesture down right, gestures 3,4 and 5 did not occur
if islabel(gesture)<>0 ;checks if gesture is labelled
gosub, %gesture% ; eg. gosub, gdr
;msgbox,,, %gesture% not yet defined,4 ;delete this line once set up
return
gesture:
mousegetpos,xpos2, ypos2
dx:=xpos2-xpos1
dy:=ypos1-ypos2
if (abs(dy)>=abs(dx))
{
if (dy>0)
track=u ;track is up
else
track=d ;down
}
else
{
if (dx>0)
track=r ;right
else
track=l ;left
}
if (abs(dy)<4 and abs(dx)<4)
track= ;not tracking at all if no significant change in x or y
xpos1:=xpos2
ypos1:=ypos2
if (track<>SubStr(gesture, 0, 1)) ;ignore track if not changing since previous track
gesture := gesture . track
return
g: ;normal right click
click, right, xpos1, ypos1
exit
gdr: ;delete examples when set up
msgbox, you drew an L
exit
gldrdl:
msgbox, you drew an S
exit
gurdurd:
msgbox, you drew an M
exit |
|
|
| Back to top |
|
 |
rodfell
Joined: 05 Oct 2007 Posts: 138 Location: Bundaberg (Bundy), Qld, Australia
|
Posted: Wed Nov 07, 2007 11:01 am Post subject: substr |
|
|
yeah i like that. i haven't got around to working out the substr function yet (still a bit of a noob). However, I would draw an M as (from bottom left) up down up down. As long as all angles are less than 45 degrees (fairly hard to make any greater than 45), the gesture for M would be gudud. N would be gudu. C would be gldr etc.
On my 24/7 ahk file, gu is maximize, gd is minimize, gl is back gr is forward. |
|
| Back to top |
|
 |
rodfell
Joined: 05 Oct 2007 Posts: 138 Location: Bundaberg (Bundy), Qld, Australia
|
Posted: Sun Nov 11, 2007 12:21 am Post subject: added a few more examples and tweaks |
|
|
added a few more examples and tweaks
| Code: |
;simple mouse gestures call subroutines based on a gesture (right button)
;the script tracks up (u) down (d) left (l) and right (r). There is a tolerance of +/- 45 degrees, so it is quite simple and accurate
;gestures can have curves. eg a circle drawn from the top and clockwise is registered as rdlu (right down left up)
;if a gesture is down (d) and right (r), like an "L", a subroutine called gdr ( for gesture down right) will be called
;if anything is labelled as gdr:, the action will be run
;as a further example, if an "S" is drawn (from top to bottom), gldrdl: (gesture left down right down left) will be called
;these 2 examples are included. See below for further examples
CoordMode, Mouse, Screen
winget, window0, id, ahk_class Progman ;not needed to make a gesture, window0 is used in subroutines called by gestures used on the desktop. see gu: subroutine example
rbutton::
if (window1<>window0) ;these 2 lines do not help the creation of gestures. The variable window2 can be used by subroutines called
window2:=window1 ;by the gestures eg. maximize previous window
mousegetpos,xpos1, ypos1,window1 ;window1 can be used by subroutines eg maximize window under cursor
gesture= ;clear previous tracking results, variable array gesture1 to gesture5
settimer, gesture, 10
return
rbutton up::
settimer, gesture, off
gesture := "g" . gesture ;eg. gdr = gesture down right
if islabel(gesture)<>0 ;checks if gesture is labelled
gosub, %gesture% ; eg. gosub, gdr
msgbox,,, %gesture% not yet defined,4
return
gesture:
mousegetpos,xpos2, ypos2
dx:=xpos2-xpos1
dy:=ypos1-ypos2
if (abs(dy)>=abs(dx))
{
if (dy>0)
track=u ;track is up
else
track=d ;down
}
else
{
if (dx>0)
track=r ;right
else
track=l ;left
}
if (abs(dy)<4 and abs(dx)<4)
track= ;not tracking at all if no significant change in x or y
xpos1:=xpos2
ypos1:=ypos2
if (track<>SubStr(gesture, 0, 1)) ;ignore track if not changing since previous track
gesture := gesture . track
return
g: ;normal right click
click, right, xpos1, ypos1
exit
;;;;;;; Examples ;;;;;;;;;;;;;;;;;;;;;;;;;;
gu: ;; gesture up ;; maximize window under cursor. maximize last window if cursor over desktop
if (window1=window0)
{
if (window2<>"")
winmaximize, ahk_id %window2%
}
else
winmaximize, ahk_id %window1%
exit
gd: ;minimize window under cursor
if (window1<>window0)
winminimize, ahk_id %window1%
exit
gl: ;browser back
winactivate, ahk_id %window1%
sendinput, {Browser_Back}
exit
gr: ;browser forward
winactivate, ahk_id %window1%
sendinput, {Browser_Forward}
exit
gdr: ;restore last window.
winrestore, ahk_id %window2%
exit
gldr: ;close window under cursor (draw a C)
if (window1<>window0)
winclose, ahk_id %window1%
exit
gldrdl:
msgbox, you drew an S
exit
gurdurd:
msgbox, you drew an M
exit
|
|
|
| Back to top |
|
 |
MarkyMark
Joined: 28 Sep 2007 Posts: 26
|
Posted: Sat Jan 19, 2008 3:30 pm Post subject: |
|
|
| Thanks rodfell for the script. Was looking for something lean and easy. Your works well. |
|
| Back to top |
|
 |
Marky Guest
|
Posted: Tue Jan 22, 2008 2:45 pm Post subject: |
|
|
| Is it possible to do a mouse gesture on a per application (ifwinactive) basis? |
|
| Back to top |
|
 |
ManaUser
Joined: 24 May 2007 Posts: 1121
|
Posted: Tue Jan 22, 2008 5:27 pm Post subject: |
|
|
You could just do this:
| Code: | gldrdl:
IfWinActive ahk_class MozillaUIWindowClass
msgbox, You drew an S, in Firefox!
Else IfWinActive ahk_class Notepad
msgbox, You drew an S, in notepad!
Else
msgbox, You drew an S, somewhere else!
exit |
That's probably the best way actually. |
|
| Back to top |
|
 |
MarkyMark
Joined: 28 Sep 2007 Posts: 26
|
Posted: Tue Jan 22, 2008 10:31 pm Post subject: |
|
|
ManaUser
Thank you. I appreciate it.  |
|
| Back to top |
|
 |
lilljimpa
Joined: 18 Apr 2007 Posts: 127
|
Posted: Wed Jan 23, 2008 11:39 am Post subject: |
|
|
how do i add a weelup and weeldown to this gesture?
ex:
gweelup:
msgbox, you scroll up
exit _________________ you'll have to excuse me...I'm from Sweden, so my English is not that good...(but now it's better cuz JSLover/Guest is helping me)... |
|
| Back to top |
|
 |
ManaUser
Joined: 24 May 2007 Posts: 1121
|
Posted: Wed Jan 23, 2008 6:28 pm Post subject: |
|
|
| lilljimpa wrote: | | how do i add a weelup and weeldown to this gesture? |
Heh, this is getting not-so-simple but here goes: (magenta parts are new)
| Code: | ;simple mouse gestures call subroutines based on a gesture (right button)
;the script tracks up (u) down (d) left (l) and right (r). There is a tolerance of +/- 45 degrees, so it is quite simple and accurate
;gestures can have curves. eg a circle drawn from the top and clockwise is registered as rdlu (right down left up)
;if a gesture is down (d) and right (r), like an "L", a subroutine called gdr ( for gesture down right) will be called
;if anything is labelled as gdr:, the action will be run
;as a further example, if an "S" is drawn (from top to bottom), gldrdl: (gesture left down right down left) will be called
;these 2 examples are included. See below for further examples
CoordMode, Mouse, Screen
winget, window0, id, ahk_class Progman ;not needed to make a gesture, window0 is used in subroutines called by gestures used on the desktop. see gu: subroutine example
rbutton::
if (window1<>window0) ;these 2 lines do not help the creation of gestures. The variable window2 can be used by subroutines called
window2:=window1 ;by the gestures eg. maximize previous window
mousegetpos,xpos1, ypos1,window1 ;window1 can be used by subroutines eg maximize window under cursor
gesture= ;clear previous tracking results, variable array gesture1 to gesture5
settimer, gesture, 10
GestureMode = 1
return
rbutton up::
settimer, gesture, off
GestureMode = 0
gesture := "g" . gesture ;eg. gdr = gesture down right
if islabel(gesture)<>0 ;checks if gesture is labelled
gosub, %gesture% ; eg. gosub, gdr
msgbox,,, %gesture% not yet defined,4
return
gesture:
mousegetpos,xpos2, ypos2
dx:=xpos2-xpos1
dy:=ypos1-ypos2
if (abs(dy)>=abs(dx))
{
if (dy>0)
track=u ;track is up
else
track=d ;down
}
else
{
if (dx>0)
track=r ;right
else
track=l ;left
}
if (abs(dy)<4 and abs(dx)<4)
track= ;not tracking at all if no significant change in x or y
xpos1:=xpos2
ypos1:=ypos2
if (track<>SubStr(gesture, 0, 1)) ;ignore track if not changing since previous track
gesture := gesture . track
return
WheelUp:: ;Since u and d are taken, we'll use + and - for the mouse wheel.
If GestureMode ;we're currently recording a gesture
{
If (SubStr(gesture, 0) != "+") ;Don't record two wheelups in a row
gesture := gesture . "+"
}
Else ;we're not recording a gesture so just do a wheelup
Send {WheelUp}
Return
WheelDown:: ;ditto for down
If GestureMode
{
If (SubStr(gesture, 0) != "-")
gesture := gesture . "-"
}
Else
Send {WheelDown}
Return
g: ;normal right click
click, right, xpos1, ypos1
exit
;;;;;;; Examples ;;;;;;;;;;;;;;;;;;;;;;;;;;
gu: ;; gesture up ;; maximize window under cursor. maximize last window if cursor over desktop
if (window1=window0)
{
if (window2<>"")
winmaximize, ahk_id %window2%
}
else
winmaximize, ahk_id %window1%
exit
gd: ;minimize window under cursor
if (window1<>window0)
winminimize, ahk_id %window1%
exit
gl: ;browser back
winactivate, ahk_id %window1%
sendinput, {Browser_Back}
exit
gr: ;browser forward
winactivate, ahk_id %window1%
sendinput, {Browser_Forward}
exit
gdr: ;restore last window.
winrestore, ahk_id %window2%
exit
gldr: ;close window under cursor (draw a C)
if (window1<>window0)
winclose, ahk_id %window1%
exit
gldrdl:
msgbox, you drew an S
exit
gurdurd:
msgbox, you drew an M
exit
g+:
MsgBox WheelUp
exit
g-:
MsgBox WheelDown
exit
gl+:
MsgBox Left-WheelUp
exit |
|
|
| Back to top |
|
 |
rodfell
Joined: 05 Oct 2007 Posts: 138 Location: Bundaberg (Bundy), Qld, Australia
|
Posted: Sat Jan 26, 2008 4:13 am Post subject: wheel up down |
|
|
| why do you need wheelup and wheel down? I tried for simplicity. If there's a good reason for it, i'll try to incorporate it. |
|
| Back to top |
|
 |
lilljimpa
Joined: 18 Apr 2007 Posts: 127
|
Posted: Sat Jan 26, 2008 3:15 pm Post subject: Re: wheel up down |
|
|
| rodfell wrote: | | why do you need wheelup and wheel down? I tried for simplicity. If there's a good reason for it, i'll try to incorporate it. |
i have my reason i have add a trancparent to the gesture, not as good i hope for but it's working nice _________________ you'll have to excuse me...I'm from Sweden, so my English is not that good...(but now it's better cuz JSLover/Guest is helping me)... |
|
| Back to top |
|
 |
rodfell
Joined: 05 Oct 2007 Posts: 138 Location: Bundaberg (Bundy), Qld, Australia
|
Posted: Sun Jan 27, 2008 3:44 am Post subject: |
|
|
| i get it now. i can see when the wheelup and down would be useful eg volume up and down. I played around with other ways of doing what you wanted but no success. the trouble is getkeystate doesn't work with wheelup and wheeldown. i have incorporated your code into my 24/7 ahk file |
|
| Back to top |
|
 |
Icarus
Joined: 24 Nov 2005 Posts: 851
|
Posted: Sun Jan 27, 2008 2:43 pm Post subject: |
|
|
A very nice and smart script.
I noticed there is one problem when gesturing diagonals - the script continuously records "dldldldldl".
I would also suggest to include diagonal as a valid gesture - this will allow to have things not possible now - for example, an "R" shaped gesture is not logged correctly now, since the leg of the R is sometimes recorded as R and sometimes as D (and sometimes as both).
I may try to do the change, if I do, I will post here. |
|
| Back to top |
|
 |
ManaUser
Joined: 24 May 2007 Posts: 1121
|
Posted: Sun Jan 27, 2008 6:18 pm Post subject: |
|
|
I think some of you are missing the point. ^_^ This was supposed to be simple, simple.
There are other more complex/advanced gestures scripts already.
Last edited by ManaUser on Tue Jan 29, 2008 11:27 pm; edited 1 time in total |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|