Show incoming fight reactions on unfocused visible players
This commit is contained in:
@@ -36,7 +36,8 @@ stay in chat history; joining or reconnecting does not replay animations.
|
||||
|
||||
Quiet sound effects play automatically with visible reactions. Sounds are
|
||||
original synthesized effects cached locally, with no external downloads. Overlays and sound are
|
||||
suppressed while the player is hidden, minimized, or another application is active.
|
||||
suppressed while the player is hidden or minimized. Visible players receive
|
||||
reactions even without keyboard focus, without activating the player window.
|
||||
Reactions also work while the detached chat window is focused.
|
||||
|
||||
Robbery votes allow one answer per person, which you can change before the vote
|
||||
|
||||
@@ -6,7 +6,7 @@ import wave
|
||||
|
||||
from PyQt6.QtCore import Qt, QTimer, QPropertyAnimation, QVariantAnimation, QPoint, QEasingCurve, QEvent
|
||||
from PyQt6.QtGui import QPainter, QPainterPath, QFont, QColor, QPen, QLinearGradient, QTransform
|
||||
from PyQt6.QtWidgets import QApplication, QWidget, QFrame, QLabel, QHBoxLayout, QVBoxLayout
|
||||
from PyQt6.QtWidgets import QWidget, QFrame, QLabel, QHBoxLayout, QVBoxLayout
|
||||
|
||||
|
||||
REACTIONS = {
|
||||
@@ -157,11 +157,7 @@ class RingsideStrip(QWidget):
|
||||
if kind not in REACTIONS or not self.video_frame.isVisible():
|
||||
return False
|
||||
owner = self.video_frame.window()
|
||||
# Avoid displaying an always-on-top effect over another application.
|
||||
active = QApplication.activeWindow()
|
||||
while active is not None and active is not owner:
|
||||
active = active.parentWidget()
|
||||
if active is None or owner.isMinimized():
|
||||
if owner.isMinimized():
|
||||
return False
|
||||
if self.owner_window is not owner:
|
||||
if self.owner_window is not None:
|
||||
@@ -211,7 +207,9 @@ class RingsideStrip(QWidget):
|
||||
|
||||
def eventFilter(self, watched, event):
|
||||
if self.isVisible():
|
||||
if event.type() in (QEvent.Type.Hide, QEvent.Type.WindowDeactivate, QEvent.Type.Close):
|
||||
if event.type() in (QEvent.Type.Hide, QEvent.Type.Close):
|
||||
self.dismiss()
|
||||
elif event.type() == QEvent.Type.WindowStateChange and self.owner_window.isMinimized():
|
||||
self.dismiss()
|
||||
elif event.type() in (QEvent.Type.Move, QEvent.Type.Resize):
|
||||
self.slide.stop()
|
||||
|
||||
@@ -44,7 +44,7 @@ def test_strip_is_native_positioned_and_does_not_steal_focus(room, qtbot, kind):
|
||||
qtbot.wait(50)
|
||||
bounds = QRect(video.mapToGlobal(QPoint(0, 0)), video.size())
|
||||
assert bounds.contains(strip.geometry())
|
||||
QApplication.sendEvent(room, QEvent(QEvent.Type.WindowDeactivate))
|
||||
QApplication.sendEvent(room, QEvent(QEvent.Type.Hide))
|
||||
assert not strip.isVisible()
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ def test_arcade_ko_covers_video_then_restores_strip(room, qtbot):
|
||||
assert overlay.ko_animation.state() == overlay.ko_animation.State.Stopped
|
||||
|
||||
|
||||
def test_sound_is_enabled_by_default_and_background_effects_are_suppressed(room, qtbot, monkeypatch):
|
||||
def test_sound_is_enabled_by_default_and_hidden_effects_are_suppressed(room, qtbot, monkeypatch):
|
||||
play = Mock()
|
||||
monkeypatch.setattr(room, '_play_reaction_sound', play)
|
||||
room.activateWindow()
|
||||
@@ -109,6 +109,29 @@ def test_sound_is_enabled_by_default_and_background_effects_are_suppressed(room,
|
||||
assert not room.ringside_strip.isVisible()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('kind', ['ko', 'bell'])
|
||||
def test_receiving_client_shows_reaction_without_focus(room, qtbot, monkeypatch, kind):
|
||||
from PyQt6.QtWidgets import QLineEdit
|
||||
other_client = QLineEdit()
|
||||
qtbot.addWidget(other_client)
|
||||
other_client.show()
|
||||
other_client.activateWindow()
|
||||
other_client.setFocus()
|
||||
qtbot.wait(30)
|
||||
assert not room.isActiveWindow()
|
||||
play = Mock()
|
||||
monkeypatch.setattr(room, '_play_reaction_sound', play)
|
||||
room.handle_fight_reaction({'kind': kind, 'username': 'Other client', 'position': 0})
|
||||
assert room.ringside_strip.isVisible()
|
||||
play.assert_called_once_with(kind)
|
||||
assert QApplication.focusWidget() is other_client
|
||||
QApplication.sendEvent(room, QEvent(QEvent.Type.WindowDeactivate))
|
||||
assert room.ringside_strip.isVisible()
|
||||
room.showMinimized()
|
||||
qtbot.wait(30)
|
||||
assert not room.ringside_strip.isVisible()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('kind', REACTIONS)
|
||||
def test_original_sound_files_are_valid_and_loadable(qtbot, tmp_path, kind):
|
||||
path = write_reaction_sound(tmp_path, kind)
|
||||
|
||||
Reference in New Issue
Block a user