forked from Boria138/PortProtonQt
feat: add continuous D-pad navigation
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
@ -4,7 +4,7 @@ from typing import Protocol, cast
|
|||||||
from evdev import InputDevice, ecodes, list_devices
|
from evdev import InputDevice, ecodes, list_devices
|
||||||
import pyudev
|
import pyudev
|
||||||
from PySide6.QtWidgets import QWidget, QStackedWidget, QApplication, QScrollArea, QLineEdit, QDialog, QMenu, QComboBox, QListView
|
from PySide6.QtWidgets import QWidget, QStackedWidget, QApplication, QScrollArea, QLineEdit, QDialog, QMenu, QComboBox, QListView
|
||||||
from PySide6.QtCore import Qt, QObject, QEvent, QPoint, Signal, Slot
|
from PySide6.QtCore import Qt, QObject, QEvent, QPoint, Signal, Slot, QTimer
|
||||||
from PySide6.QtGui import QKeyEvent
|
from PySide6.QtGui import QKeyEvent
|
||||||
from portprotonqt.logger import get_logger
|
from portprotonqt.logger import get_logger
|
||||||
from portprotonqt.image_utils import FullscreenDialog
|
from portprotonqt.image_utils import FullscreenDialog
|
||||||
@ -72,7 +72,6 @@ class InputManager(QObject):
|
|||||||
self._parent.currentDetailPage = getattr(self._parent, 'currentDetailPage', None)
|
self._parent.currentDetailPage = getattr(self._parent, 'currentDetailPage', None)
|
||||||
self._parent.current_exec_line = getattr(self._parent, 'current_exec_line', None)
|
self._parent.current_exec_line = getattr(self._parent, 'current_exec_line', None)
|
||||||
self._parent.current_add_game_dialog = getattr(self._parent, 'current_add_game_dialog', None)
|
self._parent.current_add_game_dialog = getattr(self._parent, 'current_add_game_dialog', None)
|
||||||
|
|
||||||
self.axis_deadzone = axis_deadzone
|
self.axis_deadzone = axis_deadzone
|
||||||
self.initial_axis_move_delay = initial_axis_move_delay
|
self.initial_axis_move_delay = initial_axis_move_delay
|
||||||
self.repeat_axis_move_delay = repeat_axis_move_delay
|
self.repeat_axis_move_delay = repeat_axis_move_delay
|
||||||
@ -84,6 +83,12 @@ class InputManager(QObject):
|
|||||||
self.running = True
|
self.running = True
|
||||||
self._is_fullscreen = read_fullscreen_config()
|
self._is_fullscreen = read_fullscreen_config()
|
||||||
|
|
||||||
|
# Add variables for continuous D-pad movement
|
||||||
|
self.dpad_timer = QTimer(self)
|
||||||
|
self.dpad_timer.timeout.connect(self.handle_dpad_repeat)
|
||||||
|
self.current_dpad_code = None # Tracks the current D-pad axis (e.g., ABS_HAT0X, ABS_HAT0Y)
|
||||||
|
self.current_dpad_value = 0 # Tracks the current D-pad direction value (e.g., -1, 1)
|
||||||
|
|
||||||
# Connect signals to slots
|
# Connect signals to slots
|
||||||
self.button_pressed.connect(self.handle_button_slot)
|
self.button_pressed.connect(self.handle_button_slot)
|
||||||
self.dpad_moved.connect(self.handle_dpad_slot)
|
self.dpad_moved.connect(self.handle_dpad_slot)
|
||||||
@ -239,6 +244,15 @@ class InputManager(QObject):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in handle_button_slot: {e}", exc_info=True)
|
logger.error(f"Error in handle_button_slot: {e}", exc_info=True)
|
||||||
|
|
||||||
|
def handle_dpad_repeat(self) -> None:
|
||||||
|
"""Handle repeated D-pad input while the D-pad is held."""
|
||||||
|
if self.current_dpad_code is not None and self.current_dpad_value != 0:
|
||||||
|
now = time.time()
|
||||||
|
if (now - self.last_move_time) >= self.current_axis_delay:
|
||||||
|
self.handle_dpad_slot(self.current_dpad_code, self.current_dpad_value, now)
|
||||||
|
self.last_move_time = now
|
||||||
|
self.current_axis_delay = self.repeat_axis_move_delay
|
||||||
|
|
||||||
@Slot(int, int, float)
|
@Slot(int, int, float)
|
||||||
def handle_dpad_slot(self, code: int, value: int, current_time: float) -> None:
|
def handle_dpad_slot(self, code: int, value: int, current_time: float) -> None:
|
||||||
try:
|
try:
|
||||||
@ -253,6 +267,23 @@ class InputManager(QObject):
|
|||||||
focused = QApplication.focusWidget()
|
focused = QApplication.focusWidget()
|
||||||
popup = QApplication.activePopupWidget()
|
popup = QApplication.activePopupWidget()
|
||||||
|
|
||||||
|
# Update D-pad state
|
||||||
|
if value != 0:
|
||||||
|
self.current_dpad_code = code
|
||||||
|
self.current_dpad_value = value
|
||||||
|
if not self.axis_moving:
|
||||||
|
self.axis_moving = True
|
||||||
|
self.last_move_time = current_time
|
||||||
|
self.current_axis_delay = self.initial_axis_move_delay
|
||||||
|
self.dpad_timer.start(int(self.repeat_axis_move_delay * 1000)) # Start timer (in milliseconds)
|
||||||
|
else:
|
||||||
|
self.current_dpad_code = None
|
||||||
|
self.current_dpad_value = 0
|
||||||
|
self.axis_moving = False
|
||||||
|
self.current_axis_delay = self.initial_axis_move_delay
|
||||||
|
self.dpad_timer.stop() # Stop timer when D-pad is released
|
||||||
|
return
|
||||||
|
|
||||||
# Handle SystemOverlay or AddGameDialog navigation with D-pad
|
# Handle SystemOverlay or AddGameDialog navigation with D-pad
|
||||||
if isinstance(active, QDialog) and code == ecodes.ABS_HAT0Y and value != 0:
|
if isinstance(active, QDialog) and code == ecodes.ABS_HAT0Y and value != 0:
|
||||||
if not focused or not active.focusWidget():
|
if not focused or not active.focusWidget():
|
||||||
@ -307,19 +338,6 @@ class InputManager(QObject):
|
|||||||
active.show_next()
|
active.show_next()
|
||||||
return
|
return
|
||||||
|
|
||||||
# Handle repeated D-pad movement
|
|
||||||
if value != 0:
|
|
||||||
if not self.axis_moving:
|
|
||||||
self.axis_moving = True
|
|
||||||
elif (current_time - self.last_move_time) < self.current_axis_delay:
|
|
||||||
return
|
|
||||||
self.last_move_time = current_time
|
|
||||||
self.current_axis_delay = self.repeat_axis_move_delay
|
|
||||||
else:
|
|
||||||
self.axis_moving = False
|
|
||||||
self.current_axis_delay = self.initial_axis_move_delay
|
|
||||||
return
|
|
||||||
|
|
||||||
# Library tab navigation (index 0)
|
# Library tab navigation (index 0)
|
||||||
if self._parent.stackedWidget.currentIndex() == 0 and code in (ecodes.ABS_HAT0X, ecodes.ABS_HAT0Y):
|
if self._parent.stackedWidget.currentIndex() == 0 and code in (ecodes.ABS_HAT0X, ecodes.ABS_HAT0Y):
|
||||||
focused = QApplication.focusWidget()
|
focused = QApplication.focusWidget()
|
||||||
@ -783,6 +801,7 @@ class InputManager(QObject):
|
|||||||
def cleanup(self) -> None:
|
def cleanup(self) -> None:
|
||||||
try:
|
try:
|
||||||
self.running = False
|
self.running = False
|
||||||
|
self.dpad_timer.stop()
|
||||||
if self.gamepad_thread:
|
if self.gamepad_thread:
|
||||||
self.gamepad_thread.join()
|
self.gamepad_thread.join()
|
||||||
if self.gamepad:
|
if self.gamepad:
|
||||||
|
Reference in New Issue
Block a user