feat(input_manager): added change slider size to RT and LT

Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
2025-06-14 11:49:28 +05:00
parent 66b4b82d49
commit 7becbf5de2

View File

@ -27,6 +27,8 @@ class MainWindowProtocol(Protocol):
... ...
def openSystemOverlay(self) -> None: def openSystemOverlay(self) -> None:
... ...
def on_slider_released(self) -> None:
...
stackedWidget: QStackedWidget stackedWidget: QStackedWidget
tabButtons: dict[int, QWidget] tabButtons: dict[int, QWidget]
gamesListWidget: QWidget gamesListWidget: QWidget
@ -34,18 +36,20 @@ class MainWindowProtocol(Protocol):
current_exec_line: str | None current_exec_line: str | None
current_add_game_dialog: QDialog | None current_add_game_dialog: QDialog | None
# Mapping of actions to evdev button codes, includes Xbox and Playstation controllers # Mapping of actions to evdev button codes, includes Xbox and PlayStation controllers
# https://github.com/torvalds/linux/blob/master/drivers/hid/hid-playstation.c # https://github.com/torvalds/linux/blob/master/drivers/hid/hid-playstation.c
# https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c # https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c
BUTTONS = { BUTTONS = {
'confirm': {ecodes.BTN_A, ecodes.BTN_SOUTH}, # A / Cross 'confirm': {ecodes.BTN_A, ecodes.BTN_SOUTH}, # A (Xbox) / Cross (PS)
'back': {ecodes.BTN_B, ecodes.BTN_EAST}, # B / Circle 'back': {ecodes.BTN_B, ecodes.BTN_EAST}, # B (Xbox) / Circle (PS)
'add_game': {ecodes.BTN_Y, ecodes.BTN_NORTH}, # Y / Triangle 'add_game': {ecodes.BTN_Y, ecodes.BTN_NORTH}, # Y (Xbox) / Triangle (PS)
'prev_tab': {ecodes.BTN_TL}, # LB / L1 'prev_tab': {ecodes.BTN_TL}, # LB (Xbox) / L1 (PS)
'next_tab': {ecodes.BTN_TR}, # RB / R1 'next_tab': {ecodes.BTN_TR}, # RB (Xbox) / R1 (PS)
'context_menu': {ecodes.BTN_START}, # Start / Options 'context_menu': {ecodes.BTN_START}, # Start (Xbox) / Options (PS)
'menu': {ecodes.BTN_SELECT}, # Select / Share 'menu': {ecodes.BTN_SELECT}, # Select (Xbox) / Share (PS)
'guide': {ecodes.BTN_MODE}, # Xbox / PS Home 'guide': {ecodes.BTN_MODE}, # Xbox Button / PS Button
'increase_size': {ecodes.ABS_RZ}, # RT (Xbox) / R2 (PS)
'decrease_size': {ecodes.ABS_Z}, # LT (Xbox) / L2 (PS)
} }
class InputManager(QObject): class InputManager(QObject):
@ -83,6 +87,10 @@ class InputManager(QObject):
self.running = True self.running = True
self._is_fullscreen = read_fullscreen_config() self._is_fullscreen = read_fullscreen_config()
self.rumble_effect_id: int | None = None # Store the rumble effect ID self.rumble_effect_id: int | None = None # Store the rumble effect ID
self.lt_pressed = False
self.rt_pressed = False
self.last_trigger_time = 0.0
self.trigger_cooldown = 0.2
# Add variables for continuous D-pad movement # Add variables for continuous D-pad movement
self.dpad_timer = QTimer(self) self.dpad_timer = QTimer(self)
@ -169,7 +177,7 @@ class InputManager(QObject):
@Slot(int) @Slot(int)
def handle_button_slot(self, button_code: int) -> None: def handle_button_slot(self, button_code: int) -> None:
try: try:
# Игнорировать события геймпада, если игра запущена # Ignore gamepad events if a game is launched
if getattr(self._parent, '_gameLaunched', False): if getattr(self._parent, '_gameLaunched', False):
return return
@ -235,7 +243,7 @@ class InputManager(QObject):
focused.clearSelection() focused.clearSelection()
focused.hide() focused.hide()
# Закрытие AddGameDialog на кнопку B # Close AddGameDialog on B button
if button_code in BUTTONS['back'] and isinstance(active, QDialog): if button_code in BUTTONS['back'] and isinstance(active, QDialog):
active.reject() active.reject()
return return
@ -282,6 +290,20 @@ class InputManager(QObject):
idx = (self._parent.stackedWidget.currentIndex() + 1) % len(self._parent.tabButtons) idx = (self._parent.stackedWidget.currentIndex() + 1) % len(self._parent.tabButtons)
self._parent.switchTab(idx) self._parent.switchTab(idx)
self._parent.tabButtons[idx].setFocus(Qt.FocusReason.OtherFocusReason) self._parent.tabButtons[idx].setFocus(Qt.FocusReason.OtherFocusReason)
elif button_code in BUTTONS['increase_size'] and self._parent.stackedWidget.currentIndex() == 0:
# Increase card size with RT (Xbox) / R2 (PS)
size_slider = getattr(self._parent, 'sizeSlider', None)
if size_slider:
new_value = min(size_slider.value() + 10, size_slider.maximum())
size_slider.setValue(new_value)
self._parent.on_slider_released()
elif button_code in BUTTONS['decrease_size'] and self._parent.stackedWidget.currentIndex() == 0:
# Decrease card size with LT (Xbox) / L2 (PS)
size_slider = getattr(self._parent, 'sizeSlider', None)
if size_slider:
new_value = max(size_slider.value() - 10, size_slider.minimum())
size_slider.setValue(new_value)
self._parent.on_slider_released()
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)
@ -297,7 +319,7 @@ class InputManager(QObject):
@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:
# Игнорировать события геймпада, если игра запущена # Ignore gamepad events if a game is launched
if getattr(self._parent, '_gameLaunched', False): if getattr(self._parent, '_gameLaunched', False):
return return
@ -698,9 +720,9 @@ class InputManager(QObject):
self.gamepad_thread.join() self.gamepad_thread.join()
self.gamepad_thread = threading.Thread(target=self.monitor_gamepad, daemon=True) self.gamepad_thread = threading.Thread(target=self.monitor_gamepad, daemon=True)
self.gamepad_thread.start() self.gamepad_thread.start()
# Отправляем сигнал для полноэкранного режима только если: # Send signal for fullscreen mode only if:
# 1. auto_fullscreen_gamepad включено # 1. auto_fullscreen_gamepad is enabled
# 2. fullscreen выключено (чтобы не конфликтовать с основной настройкой) # 2. fullscreen is not already enabled (to avoid conflict)
if read_auto_fullscreen_gamepad() and not read_fullscreen_config(): if read_auto_fullscreen_gamepad() and not read_fullscreen_config():
self.toggle_fullscreen.emit(True) self.toggle_fullscreen.emit(True)
except Exception as e: except Exception as e:
@ -734,6 +756,25 @@ class InputManager(QObject):
else: else:
self.button_pressed.emit(event.code) self.button_pressed.emit(event.code)
elif event.type == ecodes.EV_ABS: elif event.type == ecodes.EV_ABS:
if event.code in {ecodes.ABS_Z, ecodes.ABS_RZ}:
# Проверяем, достаточно ли времени прошло с последнего срабатывания
if now - self.last_trigger_time < self.trigger_cooldown:
continue
if event.code == ecodes.ABS_Z: # LT/L2
if event.value > 128 and not self.lt_pressed:
self.lt_pressed = True
self.button_pressed.emit(event.code)
self.last_trigger_time = now
elif event.value <= 128 and self.lt_pressed:
self.lt_pressed = False
elif event.code == ecodes.ABS_RZ: # RT/R2
if event.value > 128 and not self.rt_pressed:
self.rt_pressed = True
self.button_pressed.emit(event.code)
self.last_trigger_time = now
elif event.value <= 128 and self.rt_pressed:
self.rt_pressed = False
else:
self.dpad_moved.emit(event.code, event.value, now) self.dpad_moved.emit(event.code, event.value, now)
except OSError as e: except OSError as e:
if e.errno == 19: # ENODEV: No such device if e.errno == 19: # ENODEV: No such device