mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-01-29 00:51:53 +08:00
horizontal scrolling for otg
This commit is contained in:
@@ -421,10 +421,11 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
|
||||
async def __handle_ws_mouse_wheel_event(self, event: Dict) -> None:
|
||||
try:
|
||||
delta_x = valid_hid_mouse_wheel(event["delta"]["x"])
|
||||
delta_y = valid_hid_mouse_wheel(event["delta"]["y"])
|
||||
except Exception:
|
||||
return
|
||||
await self.__hid.send_mouse_wheel_event(delta_y)
|
||||
await self.__hid.send_mouse_wheel_event(delta_x, delta_y)
|
||||
|
||||
# ===== HID
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ MOUSE_HID = Hid(
|
||||
protocol=0,
|
||||
subclass=0,
|
||||
|
||||
report_length=6,
|
||||
report_length=7,
|
||||
|
||||
report_descriptor=bytes([
|
||||
# https://github.com/NicoHood/HID/blob/0835e6a/src/SingleReport/SingleAbsoluteMouse.cpp
|
||||
@@ -71,6 +71,15 @@ MOUSE_HID = Hid(
|
||||
0x95, 0x01, # REPORT_COUNT (1)
|
||||
0x81, 0x06, # INPUT (Data,Var,Rel)
|
||||
|
||||
# Horizontal wheel
|
||||
0x05, 0x0C, # USAGE PAGE (Consumer Devices)
|
||||
0x0A, 0x38, 0x02, # USAGE (AC Pan)
|
||||
0x15, 0x81, # LOGICAL_MINIMUM (-127)
|
||||
0x25, 0x7F, # LOGICAL_MAXIMUM (127)
|
||||
0x75, 0x08, # REPORT_SIZE (8)
|
||||
0x95, 0x01, # REPORT_COUNT (1)
|
||||
0x81, 0x06, # INPUT (Data,Var,Rel)
|
||||
|
||||
# End
|
||||
0xC0, # END_COLLECTION
|
||||
]),
|
||||
|
||||
@@ -57,7 +57,7 @@ class BaseHid(BasePlugin):
|
||||
async def send_mouse_button_event(self, button: str, state: bool) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
async def send_mouse_wheel_event(self, delta_y: int) -> None:
|
||||
async def send_mouse_wheel_event(self, delta_x: int, delta_y: int) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
async def clear_events(self) -> None:
|
||||
|
||||
@@ -121,8 +121,8 @@ class Plugin(BaseHid):
|
||||
async def send_mouse_move_event(self, to_x: int, to_y: int) -> None:
|
||||
self.__mouse_proc.send_move_event(to_x, to_y)
|
||||
|
||||
async def send_mouse_wheel_event(self, delta_y: int) -> None:
|
||||
self.__mouse_proc.send_wheel_event(delta_y)
|
||||
async def send_mouse_wheel_event(self, delta_x: int, delta_y: int) -> None:
|
||||
self.__mouse_proc.send_wheel_event(delta_x, delta_y)
|
||||
|
||||
async def clear_events(self) -> None:
|
||||
self.__keyboard_proc.send_clear_event()
|
||||
|
||||
@@ -66,9 +66,11 @@ class _MoveEvent(BaseEvent):
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class _WheelEvent(BaseEvent):
|
||||
delta_x: int
|
||||
delta_y: int
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
assert -127 <= self.delta_x <= 127
|
||||
assert -127 <= self.delta_y <= 127
|
||||
|
||||
|
||||
@@ -86,7 +88,7 @@ class MouseProcess(DeviceProcess):
|
||||
get_logger().info("Clearing HID-mouse events ...")
|
||||
if self._ensure_device():
|
||||
try:
|
||||
self._write_report(self.__make_report(0, self.__x, self.__y, 0)) # Release all buttons
|
||||
self._write_report(self.__make_report(0, self.__x, self.__y, 0, 0)) # Release all buttons
|
||||
finally:
|
||||
self._close_device()
|
||||
|
||||
@@ -103,8 +105,8 @@ class MouseProcess(DeviceProcess):
|
||||
def send_move_event(self, to_x: int, to_y: int) -> None:
|
||||
self._queue_event(_MoveEvent(to_x, to_y))
|
||||
|
||||
def send_wheel_event(self, delta_y: int) -> None:
|
||||
self._queue_event(_WheelEvent(delta_y))
|
||||
def send_wheel_event(self, delta_x: int, delta_y: int) -> None:
|
||||
self._queue_event(_WheelEvent(delta_x, delta_y))
|
||||
|
||||
# =====
|
||||
|
||||
@@ -124,34 +126,35 @@ class MouseProcess(DeviceProcess):
|
||||
self.__clear_state()
|
||||
if reopen:
|
||||
self._close_device()
|
||||
self.__send_current_state(0)
|
||||
self.__send_current_state(0, 0)
|
||||
|
||||
def __process_button_event(self, event: _ButtonEvent) -> None:
|
||||
if event.code & self.__pressed_buttons:
|
||||
# Ранее нажатую кнопку отжимаем
|
||||
self.__pressed_buttons &= ~event.code
|
||||
if not self.__send_current_state(0):
|
||||
if not self.__send_current_state(0, 0):
|
||||
return
|
||||
if event.state:
|
||||
# Нажимаем если нужно
|
||||
self.__pressed_buttons |= event.code
|
||||
self.__send_current_state(0)
|
||||
self.__send_current_state(0, 0)
|
||||
|
||||
def __process_move_event(self, event: _MoveEvent) -> None:
|
||||
self.__x = event.to_x
|
||||
self.__y = event.to_y
|
||||
self.__send_current_state(0)
|
||||
self.__send_current_state(0, 0)
|
||||
|
||||
def __process_wheel_event(self, event: _WheelEvent) -> None:
|
||||
self.__send_current_state(event.delta_y)
|
||||
self.__send_current_state(event.delta_x, event.delta_y)
|
||||
|
||||
def __send_current_state(self, delta_y: int) -> bool:
|
||||
def __send_current_state(self, delta_x: int, delta_y: int) -> bool:
|
||||
ok = False
|
||||
if self._ensure_device():
|
||||
ok = self._write_report(self.__make_report(
|
||||
buttons=self.__pressed_buttons,
|
||||
to_x=self.__x,
|
||||
to_y=self.__y,
|
||||
delta_x=delta_x,
|
||||
delta_y=delta_y,
|
||||
))
|
||||
if not ok:
|
||||
@@ -163,7 +166,7 @@ class MouseProcess(DeviceProcess):
|
||||
self.__x = 0
|
||||
self.__y = 0
|
||||
|
||||
def __make_report(self, buttons: int, to_x: int, to_y: int, delta_y: int) -> bytes:
|
||||
def __make_report(self, buttons: int, to_x: int, to_y: int, delta_x: int, delta_y: int) -> bytes:
|
||||
to_x = (to_x + 32768) // 2
|
||||
to_y = (to_y + 32768) // 2
|
||||
return struct.pack("<BHHb", buttons, to_x, to_y, delta_y)
|
||||
return struct.pack("<BHHbb", buttons, to_x, to_y, delta_y, delta_x)
|
||||
|
||||
@@ -119,10 +119,11 @@ class _MouseButtonEvent(_BoolEvent):
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class _MouseWheelEvent(_IntEvent):
|
||||
def __post_init__(self) -> None:
|
||||
assert self.x == 0 # Горизонтальная прокрутка пока не поддерживается
|
||||
assert -127 <= self.x <= 127
|
||||
assert -127 <= self.y <= 127
|
||||
|
||||
def make_command(self) -> bytes:
|
||||
# Горизонтальная прокрутка пока не поддерживается
|
||||
return b"\x14\x00" + struct.pack(">b", self.y) + b"\x00\x00"
|
||||
|
||||
|
||||
@@ -253,8 +254,8 @@ class Plugin(BaseHid, multiprocessing.Process): # pylint: disable=too-many-inst
|
||||
async def send_mouse_button_event(self, button: str, state: bool) -> None:
|
||||
await self.__send_bool_event(_MouseButtonEvent(button, state), self.__pressed_mouse_buttons)
|
||||
|
||||
async def send_mouse_wheel_event(self, delta_y: int) -> None:
|
||||
await self.__send_int_event(_MouseWheelEvent(0, delta_y))
|
||||
async def send_mouse_wheel_event(self, delta_x: int, delta_y: int) -> None:
|
||||
await self.__send_int_event(_MouseWheelEvent(delta_x, delta_y))
|
||||
|
||||
async def clear_events(self) -> None:
|
||||
if not self.__stop_event.is_set():
|
||||
|
||||
@@ -190,13 +190,19 @@ export function Mouse() {
|
||||
|
||||
let delta = {x: 0, y: 0};
|
||||
|
||||
__wheel_delta.y += event.deltaY;
|
||||
__wheel_delta.x += event.deltaX; // Horizontal scrolling
|
||||
if (Math.abs(__wheel_delta.x) >= 100) {
|
||||
delta.x = __wheel_delta.x / Math.abs(__wheel_delta.x) * (-5);
|
||||
__wheel_delta.x = 0;
|
||||
}
|
||||
|
||||
__wheel_delta.y += event.deltaY; // Vertical scrolling
|
||||
if (Math.abs(__wheel_delta.y) >= 100) {
|
||||
delta.y = __wheel_delta.y / Math.abs(__wheel_delta.y) * (-5);
|
||||
__wheel_delta.y = 0;
|
||||
}
|
||||
|
||||
if (delta.y) {
|
||||
if (delta.x || delta.y) {
|
||||
tools.debug("Mouse: scrolled:", delta);
|
||||
if (__ws) {
|
||||
__ws.send(JSON.stringify({
|
||||
|
||||
Reference in New Issue
Block a user