forked from Boria138/PortProtonQt
fix(ui): unify handling of QMessageBox and QMenu in controller
- Added _handle_common_ui_elements() for QMessageBox, QMenu, etc. - Fixed A/B behavior for single- and multi-button QMessageBox dialogs - Improved D-pad navigation and focused-button selection - Removed duplicated logic in specialized handlers Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
@@ -572,29 +572,11 @@ class InputManager(QObject):
|
|||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 1. Check active Popups (QMessageBox, QMenu)
|
# Handle common UI elements like QMessageBox, QMenu, etc.
|
||||||
popup = QApplication.activePopupWidget()
|
if self._handle_common_ui_elements(button_code):
|
||||||
if popup:
|
return
|
||||||
if isinstance(popup, QMessageBox):
|
|
||||||
if button_code in (BUTTONS['confirm'] | BUTTONS['back']):
|
|
||||||
popup.accept()
|
|
||||||
return
|
|
||||||
elif isinstance(popup, QMenu):
|
|
||||||
if button_code in BUTTONS['confirm']:
|
|
||||||
if popup.activeAction():
|
|
||||||
popup.activeAction().trigger()
|
|
||||||
elif button_code in BUTTONS['back']:
|
|
||||||
popup.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
# 2. Check Top-Level Message Boxes
|
# Winetricks-specific button handling
|
||||||
for widget in QApplication.topLevelWidgets():
|
|
||||||
if isinstance(widget, QMessageBox) and widget.isVisible():
|
|
||||||
if button_code in (BUTTONS['confirm'] | BUTTONS['back']):
|
|
||||||
widget.accept()
|
|
||||||
return
|
|
||||||
|
|
||||||
# 3. Main Logic
|
|
||||||
focused = QApplication.focusWidget()
|
focused = QApplication.focusWidget()
|
||||||
|
|
||||||
if button_code in BUTTONS['confirm']: # A: Toggle checkbox
|
if button_code in BUTTONS['confirm']: # A: Toggle checkbox
|
||||||
@@ -763,19 +745,18 @@ class InputManager(QObject):
|
|||||||
kb.on_backspace_pressed()
|
kb.on_backspace_pressed()
|
||||||
return
|
return
|
||||||
|
|
||||||
# 2. Popup Handling
|
# Handle common UI elements like QMessageBox, QMenu, etc.
|
||||||
|
if self._handle_common_ui_elements(button_code):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Handle other QDialogs
|
||||||
popup = QApplication.activePopupWidget()
|
popup = QApplication.activePopupWidget()
|
||||||
if popup:
|
if isinstance(popup, QDialog):
|
||||||
if isinstance(popup, (QMessageBox, QDialog)):
|
if button_code in BUTTONS['confirm']:
|
||||||
if button_code in (BUTTONS['confirm'] | BUTTONS['back']):
|
popup.accept()
|
||||||
popup.accept()
|
elif button_code in BUTTONS['back']:
|
||||||
return
|
popup.reject()
|
||||||
if isinstance(popup, QMenu):
|
return
|
||||||
if button_code in BUTTONS['confirm'] and popup.activeAction():
|
|
||||||
popup.activeAction().trigger()
|
|
||||||
elif button_code in BUTTONS['back']:
|
|
||||||
popup.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
# 3. Advanced Tab Combo Box Logic
|
# 3. Advanced Tab Combo Box Logic
|
||||||
table = self._get_current_settings_table()
|
table = self._get_current_settings_table()
|
||||||
@@ -1243,26 +1224,8 @@ class InputManager(QObject):
|
|||||||
self._parent.openSystemOverlay()
|
self._parent.openSystemOverlay()
|
||||||
return
|
return
|
||||||
|
|
||||||
# Handle QMenu (context menu)
|
# Handle common UI elements like QMenu and QMessageBox
|
||||||
if isinstance(popup, QMenu):
|
if self._handle_common_ui_elements(button_code):
|
||||||
if button_code in BUTTONS['confirm']:
|
|
||||||
if popup.activeAction():
|
|
||||||
popup.activeAction().trigger()
|
|
||||||
popup.close()
|
|
||||||
return
|
|
||||||
elif button_code in BUTTONS['back']:
|
|
||||||
popup.close()
|
|
||||||
return
|
|
||||||
return
|
|
||||||
|
|
||||||
# Handle QMessageBox
|
|
||||||
if isinstance(active, QMessageBox):
|
|
||||||
if button_code in BUTTONS['confirm']:
|
|
||||||
active.accept() # Close QMessageBox with the default button
|
|
||||||
return
|
|
||||||
elif button_code in BUTTONS['back']:
|
|
||||||
active.reject() # Close QMessageBox on back button
|
|
||||||
return
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Handle QComboBox
|
# Handle QComboBox
|
||||||
@@ -1463,21 +1426,40 @@ class InputManager(QObject):
|
|||||||
if not app or not active:
|
if not app or not active:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Handle SystemOverlay, AddGameDialog, or QMessageBox navigation with D-pad
|
# Handle QMessageBox navigation with D-pad (for multiple buttons)
|
||||||
if isinstance(active, QDialog) and code == ecodes.ABS_HAT0X and value != 0:
|
if isinstance(active, QMessageBox) and not isinstance(focused, QTableWidget):
|
||||||
if isinstance(active, QMessageBox): # Specific handling for QMessageBox
|
if not focused or not active.focusWidget():
|
||||||
if not focused or not active.focusWidget():
|
# If no widget is focused, focus the first focusable widget
|
||||||
# If no widget is focused, focus the first focusable widget
|
focusables = active.findChildren(QWidget, options=Qt.FindChildOption.FindChildrenRecursively)
|
||||||
focusables = active.findChildren(QWidget, options=Qt.FindChildOption.FindChildrenRecursively)
|
focusables = [w for w in focusables if w.focusPolicy() & Qt.FocusPolicy.StrongFocus]
|
||||||
focusables = [w for w in focusables if w.focusPolicy() & Qt.FocusPolicy.StrongFocus]
|
if focusables:
|
||||||
if focusables:
|
focusables[0].setFocus(Qt.FocusReason.OtherFocusReason)
|
||||||
focusables[0].setFocus(Qt.FocusReason.OtherFocusReason)
|
return
|
||||||
return
|
if code == ecodes.ABS_HAT0X and value != 0: # Horizontal navigation
|
||||||
if value > 0: # Right
|
if value > 0: # Right
|
||||||
active.focusNextChild()
|
active.focusNextChild()
|
||||||
elif value < 0: # Left
|
elif value < 0: # Left
|
||||||
active.focusPreviousChild()
|
active.focusPreviousChild()
|
||||||
|
elif code == ecodes.ABS_HAT0Y and value != 0: # Vertical navigation
|
||||||
|
if value > 0: # Down
|
||||||
|
active.focusNextChild()
|
||||||
|
elif value < 0: # Up
|
||||||
|
active.focusPreviousChild()
|
||||||
|
return
|
||||||
|
# Handle SystemOverlay, AddGameDialog, or other QDialog navigation with D-pad
|
||||||
|
elif isinstance(active, QDialog) and code == ecodes.ABS_HAT0X and value != 0:
|
||||||
|
if not focused or not active.focusWidget():
|
||||||
|
# If no widget is focused, focus the first focusable widget
|
||||||
|
focusables = active.findChildren(QWidget, options=Qt.FindChildOption.FindChildrenRecursively)
|
||||||
|
focusables = [w for w in focusables if w.focusPolicy() & Qt.FocusPolicy.StrongFocus]
|
||||||
|
if focusables:
|
||||||
|
focusables[0].setFocus(Qt.FocusReason.OtherFocusReason)
|
||||||
return
|
return
|
||||||
|
if value > 0: # Right
|
||||||
|
active.focusNextChild()
|
||||||
|
elif value < 0: # Left
|
||||||
|
active.focusPreviousChild()
|
||||||
|
return
|
||||||
elif isinstance(active, QDialog) and code == ecodes.ABS_HAT0Y and value != 0 and not isinstance(focused, QTableWidget): # Keep up/down for other dialogs
|
elif isinstance(active, QDialog) and code == ecodes.ABS_HAT0Y and value != 0 and not isinstance(focused, QTableWidget): # Keep up/down for other dialogs
|
||||||
if not focused or not active.focusWidget():
|
if not focused or not active.focusWidget():
|
||||||
# If no widget is focused, focus the first focusable widget
|
# If no widget is focused, focus the first focusable widget
|
||||||
@@ -2312,3 +2294,56 @@ class InputManager(QObject):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error during cleanup: {e}", exc_info=True)
|
logger.error(f"Error during cleanup: {e}", exc_info=True)
|
||||||
|
|
||||||
|
def _handle_common_ui_elements(self, button_code):
|
||||||
|
"""
|
||||||
|
Common handler for common UI elements like QMessageBox, QMenu, etc.
|
||||||
|
Returns True if the event was handled, False otherwise.
|
||||||
|
"""
|
||||||
|
# Check for popup widgets first
|
||||||
|
popup = QApplication.activePopupWidget()
|
||||||
|
if popup:
|
||||||
|
if isinstance(popup, QMessageBox):
|
||||||
|
self._handle_qmessagebox_button(popup, button_code)
|
||||||
|
return True
|
||||||
|
elif isinstance(popup, QMenu):
|
||||||
|
if button_code in BUTTONS['confirm']:
|
||||||
|
if popup.activeAction():
|
||||||
|
popup.activeAction().trigger()
|
||||||
|
popup.close()
|
||||||
|
elif button_code in BUTTONS['back']:
|
||||||
|
popup.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Check for top-level QMessageBox specifically
|
||||||
|
active = QApplication.activeWindow()
|
||||||
|
if isinstance(active, QMessageBox):
|
||||||
|
self._handle_qmessagebox_button(active, button_code)
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Check for top-level message boxes (additional check)
|
||||||
|
for widget in QApplication.topLevelWidgets():
|
||||||
|
if isinstance(widget, QMessageBox) and widget.isVisible() and widget != active:
|
||||||
|
self._handle_qmessagebox_button(widget, button_code)
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False # Not handled by common handler
|
||||||
|
|
||||||
|
def _handle_qmessagebox_button(self, msg_box, button_code):
|
||||||
|
"""
|
||||||
|
Unified handler for QMessageBox across all modes.
|
||||||
|
For single button dialogs, A button accepts the dialog.
|
||||||
|
For multiple button dialogs, navigate between buttons and allow selection.
|
||||||
|
"""
|
||||||
|
if button_code in BUTTONS['confirm']:
|
||||||
|
# Check if there's a focused button in the message box
|
||||||
|
focused_widget = msg_box.focusWidget()
|
||||||
|
if focused_widget:
|
||||||
|
# If a specific button is focused, click/activate it
|
||||||
|
focused_widget.click()
|
||||||
|
else:
|
||||||
|
# If no button is focused, accept with default behavior
|
||||||
|
msg_box.accept()
|
||||||
|
elif button_code in BUTTONS['back']:
|
||||||
|
# For back button, reject the dialog (typically cancels or selects cancel button)
|
||||||
|
msg_box.reject()
|
||||||
|
|||||||
Reference in New Issue
Block a user