-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0c32936
commit 261b424
Showing
12 changed files
with
446 additions
and
254 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,4 @@ | |
/slow-mouse.spec | ||
/config.json | ||
/pid.log | ||
__pycache__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
version = '1.0.0' | ||
|
||
import os | ||
import sys | ||
|
||
main_file_path = '' | ||
|
||
def is_packaged(): | ||
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'): | ||
return True | ||
else: | ||
return False | ||
|
||
def get_program_dir(): | ||
return os.path.dirname(sys.executable if is_packaged() else main_file_path) | ||
|
||
def get_program_basename(): | ||
return os.path.basename(sys.executable if is_packaged() else main_file_path) | ||
|
||
def has_touchpad_speed_support(): | ||
flag = True | ||
try: | ||
sys_win_ver = sys.getwindowsversion() | ||
if not sys_win_ver.build or sys_win_ver.build < 26000: | ||
flag = False | ||
except AttributeError: | ||
flag = False | ||
return flag |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import os, json | ||
from typing import Union | ||
|
||
from app.winparam_manager import WinparamManager | ||
|
||
class ConfigManager: | ||
defaults: dict[str, Union[int, str]] = { | ||
'key': 'RightAlt' | ||
} | ||
|
||
'File path' | ||
path: str = '' | ||
|
||
'Attached winparam manager' | ||
winparam_manager: WinparamManager | ||
|
||
'Data' | ||
data: dict[str, Union[int, str]] = {} | ||
|
||
'Read or initialize data' | ||
def __init__(self, path: str, winparam_manager: WinparamManager): | ||
self.path = path | ||
self.winparam_manager = winparam_manager | ||
|
||
for name in winparam_manager.value_obj_map: | ||
self.defaults['winparam:' + name] = -1 | ||
|
||
if not os.path.exists(self.path): | ||
open(self.path, 'w').write(json.dumps(self.defaults)) | ||
self.data = json.load(open(self.path, 'r')) | ||
|
||
'Write data' | ||
def commit(self): | ||
open(self.path, 'w').write(json.dumps(self.data)) | ||
|
||
'Get item' | ||
def get(self, key): | ||
value = self.data.get(key) | ||
if value == None: | ||
return self.defaults[key] | ||
return value | ||
|
||
'Set item' | ||
def set(self, key, val): | ||
self.data[key] = val | ||
|
||
def set_and_commit(self, key, val): | ||
self.set(key, val) | ||
self.commit() | ||
|
||
'Set values on the attached winparam manager using the configuration' | ||
def set_winparam_values(self): | ||
for name in self.winparam_manager.value_obj_map: | ||
value_obj = self.winparam_manager.value_obj_map[name] | ||
config_val = self.get('winparam:' + name) | ||
if isinstance(config_val, str) or config_val < 0: | ||
continue | ||
value_obj.set(config_val) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import os | ||
import psutil | ||
from app import app_env | ||
|
||
'The facility that prevents running multiple instances' | ||
class SelfDetect: | ||
path: str = '' | ||
def detect(self): | ||
self.path = os.path.join('', 'pid.log') | ||
if os.path.exists(self.path): | ||
fp = open(self.path,'r') | ||
split_flag = fp.read().strip().split('/') | ||
if len(split_flag) < 2: | ||
return False | ||
pid, identifier = split_flag[0], split_flag[1] | ||
fp.close() | ||
try: | ||
target_pid = int(pid) | ||
pid_iter = psutil.process_iter() | ||
for pid in pid_iter: | ||
if pid.pid == target_pid and pid.name() == identifier: | ||
return True | ||
return False | ||
except: | ||
return False | ||
else: | ||
return False | ||
def write(self): | ||
pid = os.getpid() | ||
fp = open(self.path, 'w') | ||
fp.write(str(pid) + '/' + app_env.get_program_basename()) | ||
fp.close() | ||
def clean(self): | ||
if os.path.exists(self.path): | ||
os.unlink(self.path) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import ctypes | ||
|
||
# More info on this: https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-systemparametersinfoa | ||
# https://github.com/ntdiff/headers/blob/ebe89c140e89b475005cd8696597ddf7406dfb8a/Win11_2409_24H2/x64/System32/ole32.dll/Standalone/TOUCHPAD_PARAMETERS.h#L17 | ||
|
||
# <ai-assisted-content> | ||
|
||
# Define the enums with actual values | ||
class LEGACY_TOUCHPAD_FEATURES(ctypes.c_uint): | ||
LEGACY_TOUCHPAD_FEATURE_NONE = 0 | ||
LEGACY_TOUCHPAD_FEATURE_ENABLE_DISABLE = 1 | ||
LEGACY_TOUCHPAD_FEATURE_REVERSE_SCROLL_DIRECTION = 4 | ||
|
||
class TOUCHPAD_SENSITIVITY_LEVEL(ctypes.c_uint): | ||
TOUCHPAD_SENSITIVITY_LEVEL_MOST_SENSITIVE = 0 | ||
TOUCHPAD_SENSITIVITY_LEVEL_HIGH_SENSITIVITY = 1 | ||
TOUCHPAD_SENSITIVITY_LEVEL_MEDIUM_SENSITIVITY = 2 | ||
TOUCHPAD_SENSITIVITY_LEVEL_LOW_SENSITIVITY = 3 | ||
TOUCHPAD_SENSITIVITY_LEVEL_LEAST_SENSITIVE = 4 | ||
|
||
# Define the structure for the bitfields | ||
class TouchpadFlags1(ctypes.Structure): | ||
_fields_ = [ | ||
("touchpadPresent", ctypes.c_int, 1), | ||
("legacyTouchpadPresent", ctypes.c_int, 1), | ||
("externalMousePresent", ctypes.c_int, 1), | ||
("touchpadEnabled", ctypes.c_int, 1), | ||
("touchpadActive", ctypes.c_int, 1), | ||
("feedbackSupported", ctypes.c_int, 1), | ||
("clickForceSupported", ctypes.c_int, 1), | ||
("Reserved1", ctypes.c_int, 25), | ||
] | ||
|
||
class TouchpadFlags2(ctypes.Structure): | ||
_fields_ = [ | ||
("allowActiveWhenMousePresent", ctypes.c_int, 1), | ||
("feedbackEnabled", ctypes.c_int, 1), | ||
("tapEnabled", ctypes.c_int, 1), | ||
("tapAndDragEnabled", ctypes.c_int, 1), | ||
("twoFingerTapEnabled", ctypes.c_int, 1), | ||
("rightClickZoneEnabled", ctypes.c_int, 1), | ||
("mouseAccelSettingHonored", ctypes.c_int, 1), | ||
("panEnabled", ctypes.c_int, 1), | ||
("zoomEnabled", ctypes.c_int, 1), | ||
("scrollDirectionReversed", ctypes.c_int, 1), | ||
("Reserved2", ctypes.c_int, 22), | ||
] | ||
|
||
# Define the main structure | ||
class TOUCHPAD_PARAMETERS(ctypes.Structure): | ||
_fields_ = [ | ||
("versionNumber", ctypes.c_uint), | ||
("maxSupportedContacts", ctypes.c_uint), | ||
("legacyTouchpadFeatures", LEGACY_TOUCHPAD_FEATURES), | ||
("flags1", TouchpadFlags1), | ||
("flags2", TouchpadFlags2), | ||
("sensitivityLevel", TOUCHPAD_SENSITIVITY_LEVEL), | ||
("cursorSpeed", ctypes.c_uint), | ||
("feedbackIntensity", ctypes.c_uint), | ||
("clickForceSensitivity", ctypes.c_uint), | ||
("rightClickZoneWidth", ctypes.c_uint), | ||
("rightClickZoneHeight", ctypes.c_uint), | ||
] | ||
|
||
# </ai-assisted-content> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from app import winparam_values | ||
|
||
class WinparamManager: | ||
value_obj_map: dict[str, winparam_values.ValueInterface] = {} | ||
initial_value_map: dict[str, int] = {} | ||
|
||
def __init__(self): | ||
values_to_init: list[winparam_values.ValueInterface] = [ | ||
winparam_values.ValueInterfaceMouseSpeed(), | ||
winparam_values.ValueInterfaceHScroll(), | ||
winparam_values.ValueInterfaceVScroll(), | ||
winparam_values.ValueInterfaceTouchpadSpeed() | ||
] | ||
for value in values_to_init: | ||
if not value.is_available(): | ||
continue | ||
self.value_obj_map[value.name()] = value | ||
self.retrieve_initials() | ||
|
||
def retrieve_initials(self): | ||
for name in self.value_obj_map: | ||
value = self.value_obj_map[name] | ||
self.initial_value_map[name] = value.get() | ||
# print('initials', self.initial_value_map) | ||
|
||
def revert_initials(self): | ||
for name in self.value_obj_map: | ||
value = self.value_obj_map[name] | ||
value.set(self.initial_value_map[name]) | ||
|
||
def set_values(self, value_dict: dict[str, int]): | ||
for name in self.value_obj_map: | ||
value = self.value_obj_map[name] | ||
to_set = value_dict.get(name) | ||
if to_set == None: | ||
continue | ||
value.set(to_set) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import ctypes | ||
from app.touchpad_params import TOUCHPAD_PARAMETERS | ||
from app import app_env | ||
|
||
def set_sys_value(key, value): | ||
ctypes.windll.user32.SystemParametersInfoA(key, value, value, 0) | ||
|
||
def get_sys_value(key): | ||
ptr = ctypes.c_void_p(1) | ||
ctypes.windll.user32.SystemParametersInfoA(key, 0, ctypes.byref(ptr), 0) | ||
val = ptr.value | ||
if val == None: | ||
return 0 | ||
if(val < 1): return 1 | ||
if(val > 20): return 20 | ||
return val | ||
|
||
class ValueInterface: | ||
def name(self) -> str: | ||
return '?' | ||
def menu_entry(self) -> str: | ||
return self.name() | ||
def is_available(self) -> bool: | ||
return True | ||
def get(self) -> int: | ||
raise NotImplemented() | ||
def set(self, value) -> None: | ||
raise NotImplemented() | ||
|
||
class ValueInterfaceMouseSpeed(ValueInterface): | ||
def name(self): | ||
return 'mouse_speed' | ||
def menu_entry(self) -> str: | ||
return 'Reduced &Mouse Speed' | ||
def get(self): | ||
return get_sys_value(112) | ||
def set(self, value): | ||
set_sys_value(113, value) | ||
|
||
class ValueInterfaceHScroll(ValueInterface): | ||
def name(self): | ||
return 'hscroll_speed' | ||
def menu_entry(self) -> str: | ||
return 'Reduced &H-scroll Speed' | ||
def get(self): | ||
return get_sys_value(0x6C) | ||
def set(self, value): | ||
set_sys_value(0x6D, value) | ||
|
||
class ValueInterfaceVScroll(ValueInterface): | ||
def name(self): | ||
return 'vscroll_speed' | ||
def menu_entry(self) -> str: | ||
return 'Reduced &V-scroll Speed' | ||
def get(self): | ||
return get_sys_value(0x68) | ||
def set(self, value): | ||
set_sys_value(0x69, value) | ||
|
||
class ValueInterfaceTouchpadSpeed(ValueInterface): | ||
def name(self): | ||
return 'touchpad_speed' | ||
def menu_entry(self) -> str: | ||
return 'Reduced &Touchpad Speed' | ||
def is_available(self): | ||
return super().is_available() and app_env.has_touchpad_speed_support() | ||
def get(self): | ||
params = TOUCHPAD_PARAMETERS() | ||
params.versionNumber = 1 | ||
ctypes.windll.user32.SystemParametersInfoA(0xAE, ctypes.sizeof(params), ctypes.byref(params), 0) | ||
return params.cursorSpeed | ||
def set(self, value): | ||
params = TOUCHPAD_PARAMETERS() | ||
params.versionNumber = 1 | ||
ctypes.windll.user32.SystemParametersInfoA(0xAE, ctypes.sizeof(params), ctypes.byref(params), 0) | ||
params.cursorSpeed = value | ||
ctypes.windll.user32.SystemParametersInfoA(0xAF, ctypes.sizeof(params), ctypes.byref(params), 0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
@echo off | ||
pyinstaller -F -w -i icon/main.ico slow-mouse.py --add-data "./icon/main.png;./icon" | ||
pyinstaller -F -w -i icon/main.ico main.py --add-data "./icon/main.png;./icon" -n slow-mouse |
Oops, something went wrong.