Skip to content

Instantly share code, notes, and snippets.

@ClassicOldSong
Last active January 26, 2024 07:35
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save ClassicOldSong/6eec077dc54e62ab68c2ab29b03713cc to your computer and use it in GitHub Desktop.
Save ClassicOldSong/6eec077dc54e62ab68c2ab29b03713cc to your computer and use it in GitHub Desktop.
AHK for enhancing GPD Pocket. Run pocket_enhancement.ahk. Feature: Esc + Mouse movenent = ScrollWheel, CapsLock + PrtScn = Region Screen Capture
; Instantiate this class and pass it a func name or a Function Object
; The specified function will be called with the delta move for the X and Y axes
; Normally, there is no windows message "mouse stopped", so one is simulated.
; After 10ms of no mouse movement, the callback is called with 0 for X and Y
Class MouseDelta {
State := 0
__New(callback){
;~ this.TimeoutFn := this.TimeoutFunc.Bind(this)
this.MouseMovedFn := this.MouseMoved.Bind(this)
this.Callback := callback
}
Start(){
static DevSize := 8 + A_PtrSize, RIDEV_INPUTSINK := 0x00000100
; Register mouse for WM_INPUT messages.
VarSetCapacity(RAWINPUTDEVICE, DevSize)
NumPut(1, RAWINPUTDEVICE, 0, "UShort")
NumPut(2, RAWINPUTDEVICE, 2, "UShort")
NumPut(RIDEV_INPUTSINK, RAWINPUTDEVICE, 4, "Uint")
; WM_INPUT needs a hwnd to route to, so get the hwnd of the AHK Gui.
; It doesn't matter if the GUI is showing, it still exists
Gui +hwndhwnd
NumPut(hwnd, RAWINPUTDEVICE, 8, "Uint")
this.RAWINPUTDEVICE := RAWINPUTDEVICE
DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize )
OnMessage(0x00FF, this.MouseMovedFn)
this.State := 1
return this ; allow chaining
}
Stop(){
static RIDEV_REMOVE := 0x00000001
static DevSize := 8 + A_PtrSize
OnMessage(0x00FF, this.MouseMovedFn, 0)
RAWINPUTDEVICE := this.RAWINPUTDEVICE
NumPut(RIDEV_REMOVE, RAWINPUTDEVICE, 4, "Uint")
DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize )
this.State := 0
return this ; allow chaining
}
SetState(state){
if (state && !this.State)
this.Start()
else if (!state && this.State)
this.Stop()
return this ; allow chaining
}
Delete(){
this.Stop()
;~ this.TimeoutFn := ""
this.MouseMovedFn := ""
}
; Called when the mouse moved.
; Messages tend to contain small (+/- 1) movements, and happen frequently (~20ms)
MouseMoved(wParam, lParam){
Critical
; RawInput statics
static DeviceSize := 2 * A_PtrSize, iSize := 0, sz := 0, pcbSize:=8+2*A_PtrSize, offsets := {x: (20+A_PtrSize*2), y: (24+A_PtrSize*2)}, uRawInput
static axes := {x: 1, y: 2}
; Get hDevice from RAWINPUTHEADER to identify which mouse this data came from
VarSetCapacity(header, pcbSize, 0)
If (!DllCall("GetRawInputData", "UPtr", lParam, "uint", 0x10000005, "UPtr", &header, "Uint*", pcbSize, "Uint", pcbSize) or ErrorLevel)
Return 0
ThisMouse := NumGet(header, 8, "UPtr")
; Find size of rawinput data - only needs to be run the first time.
if (!iSize){
r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", 0, "UInt*", iSize, "UInt", 8 + (A_PtrSize * 2))
VarSetCapacity(uRawInput, iSize)
}
sz := iSize ; param gets overwritten with # of bytes output, so preserve iSize
; Get RawInput data
r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", &uRawInput, "UInt*", sz, "UInt", 8 + (A_PtrSize * 2))
x := 0, y := 0 ; Ensure we always report a number for an axis. Needed?
x := NumGet(&uRawInput, offsets.x, "Int")
y := NumGet(&uRawInput, offsets.y, "Int")
this.Callback.(ThisMouse, x, y)
;~ ; There is no message for "Stopped", so simulate one
;~ fn := this.TimeoutFn
;~ SetTimer, % fn, -50
}
;~ TimeoutFunc(){
;~ this.Callback.("", 0, 0)
;~ }
}
#NoEnv
#SingleInstance force
#include MouseDelta.ahk
ScrollMode := 1
Scrolled := 1
md := new MouseDelta("MouseEvent")
hotkey, % ShiftKey, ShiftKeyPressed
hotkey, % ShiftKey " up", ShiftKeyReleased
return
ShiftKeyPressed:
BlockInput, MouseMove
ScrollMode := 0
md.SetState(!ScrollMode)""
return
ShiftKeyReleased:
BlockInput, MouseMoveOff
ScrollMode := 1
md.SetState(!ScrollMode)
if (!Scrolled) {
Send {%ShiftKey%}
}
Scrolled := 0
return
; Gets called when mouse moves or stops
; x and y are DELTA moves (Amount moved since last message), NOT coordinates.
MouseEvent(MouseID, x := 0, y := 0) {
global ScaleFactor, Scrolled
if (MouseID) {
; x *= ScaleFactor, y *= ScaleFactor
; DllCall("mouse_event",uint,1,int, x * -1 ,int, y * -1 ,ui nt,0,int,0)
Scrolled := 1
DllCall("mouse_event", uint, 0x01000, int, x, int, y, uint, x * ScaleFactor * -1, int, 0)
DllCall("mouse_event", uint, 0x800, int, x, int, y, uint, y * ScaleFactor, int, 0)
}
}
; HotKeys to change ScaleFactor
CapsLock & -::
ScaleFactor -= 1
if (ScaleFactor <= 0) {
ScaleFactor := 1
}
ShowScrollSpeed()
return
CapsLock & +::
ScaleFactor += 1
ShowScrollSpeed()
return
ShowScrollSpeed() {
global ScaleFactor
ToolTip, Scroll Speed: %ScaleFactor%
SetTimer, RemoveToolTip, Off
SetTimer, RemoveToolTip, 500
}
RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
return
; Pocket Enhancement v1.1.0
; By ClassicOldSong
; https://ccoooss.com
; https://gist.github.com/ClassicOldSong/6eec077dc54e62ab68c2ab29b03713cc
#NoEnv
#SingleInstance
SendMode Input
SetWorkingDir %A_ScriptDir%
; ============= START USER-CONFIGURABLE SECTION =============
ShiftKey := "Esc" ; The key used to switch to scrollwheel. Can be any key name from the AHK Key list: https://autohotkey.com/docs/KeyList.htm
ScaleFactor := 10 ; The amount to multiply movement when scrolling
; ============= END USER-CONFIGURABLE SECTION =============
#Include, mousewheel.ahk
CapsLock & i::Up
CapsLock & j::Left
CapsLock & k::Down
CapsLock & l::Right
CapsLock & a::MButton
CapsLock & q::^#Right
CapsLock & e::^#Left
CapsLock & PrintScreen::#+s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment