diff --git a/desktop-client/room_widget.py b/desktop-client/room_widget.py index 7437925..b36eeeb 100644 --- a/desktop-client/room_widget.py +++ b/desktop-client/room_widget.py @@ -209,6 +209,12 @@ class RoomWidget(QWidget): layout.addWidget(video_container, 1) layout.addWidget(self.chat_container) + # Prevent UI components from stealing focus (which breaks spacebar shortcuts) + for w in [self.copy_code_btn, self.leave_btn, self.play_btn, self.fullscreen_btn, + self.chat_send_btn, self.seekbar, self.volume_slider, self.chat_messages]: + w.setFocusPolicy(Qt.FocusPolicy.NoFocus) + self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) + # Instantiate the VLC Player Wrapper self.vlc_player = VLCSyncPlayer(self.video_frame) self.vlc_player.signals.time_changed.connect(self.on_vlc_time) @@ -259,6 +265,77 @@ class RoomWidget(QWidget): self.chat_container.hide() self.topbar.hide() + def toggle_mute(self): + current_vol = self.vlc_player.get_volume() + if current_vol > 0: + self._last_volume = current_vol + self.on_volume_changed(0) + self.volume_slider.setValue(0) + else: + vol = getattr(self, '_last_volume', 100) + self.on_volume_changed(vol) + self.volume_slider.setValue(vol) + + def seek_relative(self, offset_ms): + length_ms = self.vlc_player.get_length() + if length_ms > 0: + current_ms = self.vlc_player.current_time_ms + target_ms = max(0, min(current_ms + offset_ms, length_ms)) + req = self._tell_vlc_and_expect("seek", target_ms / 1000.0) + self.sync_action_requested.emit("seek", target_ms / 1000.0, req) + + def change_volume(self, offset): + new_vol = max(0, min(100, self.volume_slider.value() + offset)) + self.volume_slider.setValue(new_vol) + self.on_volume_changed(new_vol) + + def mousePressEvent(self, event): + self.setFocus() + super().mousePressEvent(event) + + def keyPressEvent(self, event): + # Allow typing in input fields without triggering shortcuts + focus_widget = QApplication.focusWidget() + if isinstance(focus_widget, QLineEdit) or isinstance(focus_widget, QTextEdit): + if event.key() == Qt.Key.Key_Escape: + focus_widget.clearFocus() + self.setFocus() + event.accept() + else: + super().keyPressEvent(event) + return + + if event.key() == Qt.Key.Key_Space: + self.toggle_playback() + event.accept() + elif event.key() == Qt.Key.Key_F: + self.toggle_fullscreen() + event.accept() + elif event.key() == Qt.Key.Key_M: + self.toggle_mute() + event.accept() + elif event.key() == Qt.Key.Key_Left: + self.seek_relative(-5000) + event.accept() + elif event.key() == Qt.Key.Key_Right: + self.seek_relative(5000) + event.accept() + elif event.key() == Qt.Key.Key_Up: + self.change_volume(5) + event.accept() + elif event.key() == Qt.Key.Key_Down: + self.change_volume(-5) + event.accept() + elif event.key() == Qt.Key.Key_Escape: + if self.window().isFullScreen(): + self.toggle_fullscreen() + event.accept() + elif event.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter): + self.chat_input.setFocus() + event.accept() + else: + super().keyPressEvent(event) + def copy_room_code(self): if self.room_code: QApplication.clipboard().setText(self.room_code) diff --git a/desktop-client/vlc_player.py b/desktop-client/vlc_player.py index af05d5c..5518e12 100644 --- a/desktop-client/vlc_player.py +++ b/desktop-client/vlc_player.py @@ -16,7 +16,8 @@ class VLCSyncPlayer: # Initialize VLC instance # --no-xlib prevents crashes on Linux # --drop-late-frames improves sync by not delaying playback when CPU is slow - self.instance = vlc.Instance("--no-xlib", "--drop-late-frames") + # --no-keyboard stops VLC from capturing and swallowing keyboard events + self.instance = vlc.Instance("--no-xlib", "--drop-late-frames", "--no-keyboard") self.media_player = self.instance.media_player_new() # Embed the VLC player into the provided PyQt QFrame