mirror of https://gitlab.com/openlp/openlp.git
Merge branch 'screen-flicker-fix' into 'master'
Handling screen display change corner cases Closes #1212 See merge request openlp/openlp!509
This commit is contained in:
commit
75020cdba4
|
@ -163,7 +163,7 @@ class Screen(object):
|
||||||
Callback function for when the screens geometry changes
|
Callback function for when the screens geometry changes
|
||||||
"""
|
"""
|
||||||
self.geometry = geometry
|
self.geometry = geometry
|
||||||
Registry().execute('config_screen_changed')
|
ConfigScreenChangedEmitter().emit()
|
||||||
|
|
||||||
|
|
||||||
class ScreenList(metaclass=Singleton):
|
class ScreenList(metaclass=Singleton):
|
||||||
|
@ -396,7 +396,7 @@ class ScreenList(metaclass=Singleton):
|
||||||
is_primary=self.application.primaryScreen() == changed_screen))
|
is_primary=self.application.primaryScreen() == changed_screen))
|
||||||
self.find_new_display_screen()
|
self.find_new_display_screen()
|
||||||
changed_screen.geometryChanged.connect(self.screens[-1].on_geometry_changed)
|
changed_screen.geometryChanged.connect(self.screens[-1].on_geometry_changed)
|
||||||
Registry().execute('config_screen_changed')
|
ConfigScreenChangedEmitter().emit()
|
||||||
|
|
||||||
def on_screen_removed(self, removed_screen):
|
def on_screen_removed(self, removed_screen):
|
||||||
"""
|
"""
|
||||||
|
@ -417,7 +417,7 @@ class ScreenList(metaclass=Singleton):
|
||||||
self.screens.pop(removed_screen_number)
|
self.screens.pop(removed_screen_number)
|
||||||
if removed_screen_is_display:
|
if removed_screen_is_display:
|
||||||
self.find_new_display_screen()
|
self.find_new_display_screen()
|
||||||
Registry().execute('config_screen_changed')
|
ConfigScreenChangedEmitter().emit()
|
||||||
|
|
||||||
def on_primary_screen_changed(self):
|
def on_primary_screen_changed(self):
|
||||||
"""
|
"""
|
||||||
|
@ -426,5 +426,21 @@ class ScreenList(metaclass=Singleton):
|
||||||
for screen in self.screens:
|
for screen in self.screens:
|
||||||
screen.is_primary = self.application.primaryScreen().geometry() == screen.geometry
|
screen.is_primary = self.application.primaryScreen().geometry() == screen.geometry
|
||||||
self.find_new_display_screen()
|
self.find_new_display_screen()
|
||||||
|
ConfigScreenChangedEmitter().emit()
|
||||||
|
|
||||||
|
|
||||||
|
SCREEN_CHANGED_DEBOUNCE_TIMEOUT = 350
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigScreenChangedEmitter(metaclass=Singleton):
|
||||||
|
def __init__(self):
|
||||||
|
self.timer = QtCore.QTimer(None)
|
||||||
|
self.timer.setInterval(SCREEN_CHANGED_DEBOUNCE_TIMEOUT)
|
||||||
|
self.timer.setSingleShot(True)
|
||||||
|
self.timer.timeout.connect(self.__do_emit_config_screen_changed)
|
||||||
|
|
||||||
|
def emit(self):
|
||||||
|
self.timer.start()
|
||||||
|
|
||||||
|
def __do_emit_config_screen_changed(self):
|
||||||
Registry().execute('config_screen_changed')
|
Registry().execute('config_screen_changed')
|
||||||
|
|
|
@ -130,11 +130,13 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin):
|
||||||
"""
|
"""
|
||||||
This is a window to show the output
|
This is a window to show the output
|
||||||
"""
|
"""
|
||||||
def __init__(self, parent=None, screen=None, can_show_startup_screen=True):
|
def __init__(self, parent=None, screen=None, can_show_startup_screen=True, start_hidden=False,
|
||||||
|
after_loaded_callback=None):
|
||||||
"""
|
"""
|
||||||
Create the display window
|
Create the display window
|
||||||
"""
|
"""
|
||||||
super(DisplayWindow, self).__init__(parent)
|
super(DisplayWindow, self).__init__(parent)
|
||||||
|
self.after_loaded_callback = after_loaded_callback
|
||||||
# Gather all flags for the display window
|
# Gather all flags for the display window
|
||||||
flags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | QtCore.Qt.WindowStaysOnTopHint
|
flags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | QtCore.Qt.WindowStaysOnTopHint
|
||||||
if self.settings.value('advanced/x11 bypass wm'):
|
if self.settings.value('advanced/x11 bypass wm'):
|
||||||
|
@ -183,7 +185,7 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin):
|
||||||
self.update_from_screen(screen)
|
self.update_from_screen(screen)
|
||||||
self.is_display = True
|
self.is_display = True
|
||||||
# Only make visible on single monitor setup if setting enabled.
|
# Only make visible on single monitor setup if setting enabled.
|
||||||
if len(ScreenList()) > 1 or self.settings.value('core/display on monitor'):
|
if not start_hidden and (len(ScreenList()) > 1 or self.settings.value('core/display on monitor')):
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
|
@ -303,6 +305,8 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties, LogMixin):
|
||||||
self.set_scale(self.scale)
|
self.set_scale(self.scale)
|
||||||
if self._can_show_startup_screen:
|
if self._can_show_startup_screen:
|
||||||
self.set_startup_screen()
|
self.set_startup_screen()
|
||||||
|
if self.after_loaded_callback:
|
||||||
|
self.after_loaded_callback()
|
||||||
|
|
||||||
def run_javascript(self, script, is_sync=False):
|
def run_javascript(self, script, is_sync=False):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -25,6 +25,7 @@ import shutil
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tempfile import gettempdir
|
from tempfile import gettempdir
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
@ -526,6 +527,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
|
||||||
# Starting up web services
|
# Starting up web services
|
||||||
self.http_server = HttpServer(self)
|
self.http_server = HttpServer(self)
|
||||||
self.ws_server = WebSocketServer()
|
self.ws_server = WebSocketServer()
|
||||||
|
self.screen_updating_lock = Lock()
|
||||||
|
|
||||||
def _wait_for_threads(self):
|
def _wait_for_threads(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1015,25 +1017,35 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
|
||||||
"""
|
"""
|
||||||
The screen has changed so we have to update components such as the renderer.
|
The screen has changed so we have to update components such as the renderer.
|
||||||
"""
|
"""
|
||||||
self.application.set_busy_cursor()
|
try:
|
||||||
self.renderer.resize(self.live_controller.screens.current.display_geometry.size())
|
self.screen_updating_lock.acquire()
|
||||||
self.preview_controller.screen_size_changed()
|
# if a warning has been shown within the last 5 seconds, skip showing again to avoid spamming user,
|
||||||
self.live_controller.setup_displays()
|
# also do not show if the settings window is visible
|
||||||
self.live_controller.screen_size_changed()
|
has_shown_messagebox_recently = self.screen_change_timestamp \
|
||||||
self.setFocus()
|
and (datetime.now() - self.screen_change_timestamp).seconds < 5
|
||||||
self.activateWindow()
|
should_show_messagebox = self.settings_form.isHidden() and not has_shown_messagebox_recently
|
||||||
self.application.set_normal_cursor()
|
if should_show_messagebox:
|
||||||
# if a warning has been shown within the last 5 seconds, skip showing again to avoid spamming user,
|
QtWidgets.QMessageBox.warning(self, translate('OpenLP.MainWindow', 'Screen setup has changed'),
|
||||||
# also do not show if the settings window is visible
|
translate('OpenLP.MainWindow',
|
||||||
if not self.settings_form.isVisible() and not self.screen_change_timestamp or \
|
'The screen setup has changed. '
|
||||||
self.screen_change_timestamp and (datetime.now() - self.screen_change_timestamp).seconds > 5:
|
'OpenLP will try to automatically select a display screen, but '
|
||||||
self.screen_change_timestamp = datetime.now()
|
'you should consider updating the screen settings.'),
|
||||||
QtWidgets.QMessageBox.warning(self, translate('OpenLP.MainWindow', 'Screen setup has changed'),
|
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
|
||||||
translate('OpenLP.MainWindow',
|
self.screen_change_timestamp = datetime.now()
|
||||||
'The screen setup has changed. '
|
self.application.set_busy_cursor()
|
||||||
'OpenLP will try to automatically select a display screen, but '
|
self.renderer.resize(self.live_controller.screens.current.display_geometry.size())
|
||||||
'you should consider updating the screen settings.'),
|
self.preview_controller.screen_size_changed()
|
||||||
QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
|
self.live_controller.setup_displays()
|
||||||
|
self.live_controller.screen_size_changed()
|
||||||
|
self.setFocus()
|
||||||
|
self.activateWindow()
|
||||||
|
self.application.set_normal_cursor()
|
||||||
|
# Forcing application to process events to trigger display update
|
||||||
|
# We need to wait a little of time as it would otherwise need a mouse move
|
||||||
|
# to process the screen change, for example
|
||||||
|
QtCore.QTimer.singleShot(150, lambda: self.application.process_events())
|
||||||
|
finally:
|
||||||
|
self.screen_updating_lock.release()
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -181,12 +181,22 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||||
self.close_displays()
|
self.close_displays()
|
||||||
for screen in self.screens:
|
for screen in self.screens:
|
||||||
if screen.is_display:
|
if screen.is_display:
|
||||||
display = DisplayWindow(self, screen)
|
will_start_hidden = self._current_hide_mode == HideMode.Screen
|
||||||
|
display = DisplayWindow(self, screen, start_hidden=will_start_hidden,
|
||||||
|
after_loaded_callback=self._display_after_loaded_callback)
|
||||||
self.displays.append(display)
|
self.displays.append(display)
|
||||||
self._reset_blank(False)
|
self._reset_blank(False)
|
||||||
if self.display:
|
if self.display:
|
||||||
self.__add_actions_to_widget(self.display)
|
self.__add_actions_to_widget(self.display)
|
||||||
|
|
||||||
|
def _display_after_loaded_callback(self):
|
||||||
|
# As the display was reloaded, we'll need to process current item again
|
||||||
|
if self.service_item:
|
||||||
|
self._process_item(self.service_item, self.selected_row, is_reloading=True)
|
||||||
|
# Restoring last hide mode
|
||||||
|
if self._current_hide_mode:
|
||||||
|
self.display.hide_display(self._current_hide_mode)
|
||||||
|
|
||||||
def close_displays(self):
|
def close_displays(self):
|
||||||
"""
|
"""
|
||||||
Close all open displays
|
Close all open displays
|
||||||
|
@ -929,12 +939,13 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||||
for display in self.displays:
|
for display in self.displays:
|
||||||
display.set_theme(theme_data, service_item_type=service_item.service_item_type)
|
display.set_theme(theme_data, service_item_type=service_item.service_item_type)
|
||||||
|
|
||||||
def _process_item(self, service_item, slide_no):
|
def _process_item(self, service_item, slide_no, is_reloading=False):
|
||||||
"""
|
"""
|
||||||
Loads a ServiceItem into the system from ServiceManager. Display the slide number passed.
|
Loads a ServiceItem into the system from ServiceManager. Display the slide number passed.
|
||||||
|
|
||||||
:param service_item: The current service item
|
:param service_item: The current service item
|
||||||
:param slide_no: The slide number to select
|
:param slide_no: The slide number to select
|
||||||
|
:param is_reloading: If the controller is reloading the current item, due to a display update (for example).
|
||||||
"""
|
"""
|
||||||
self.log_debug('_process_item start')
|
self.log_debug('_process_item start')
|
||||||
self.on_stop_loop()
|
self.on_stop_loop()
|
||||||
|
@ -1044,7 +1055,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
|
||||||
self.application.process_events()
|
self.application.process_events()
|
||||||
self.ignore_toolbar_resize_events = False
|
self.ignore_toolbar_resize_events = False
|
||||||
self.on_controller_size_changed()
|
self.on_controller_size_changed()
|
||||||
if self.settings.value('core/auto unblank'):
|
if not is_reloading and self.settings.value('core/auto unblank'):
|
||||||
self.set_hide_mode(None)
|
self.set_hide_mode(None)
|
||||||
self.log_debug('_process_item end')
|
self.log_debug('_process_item end')
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ from pathlib import Path
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
|
from openlp.core.display.screens import Screen
|
||||||
|
|
||||||
# Mock QtWebEngineWidgets
|
# Mock QtWebEngineWidgets
|
||||||
sys.modules['PyQt5.QtWebEngineWidgets'] = MagicMock()
|
sys.modules['PyQt5.QtWebEngineWidgets'] = MagicMock()
|
||||||
|
@ -123,6 +124,48 @@ def test_not_macos_toolwindow_attribute_set(mocked_is_macosx, mock_settings, dis
|
||||||
assert display_window.testAttribute(QtCore.Qt.WA_MacAlwaysShowToolWindow) is False
|
assert display_window.testAttribute(QtCore.Qt.WA_MacAlwaysShowToolWindow) is False
|
||||||
|
|
||||||
|
|
||||||
|
@patch.object(DisplayWindow, 'show')
|
||||||
|
def test_not_shown_if_start_hidden_is_set(mocked_show, display_window_env, mock_settings):
|
||||||
|
"""
|
||||||
|
Tests if DisplayWindow's .show() method is not called on constructor if constructed with start_hidden=True
|
||||||
|
"""
|
||||||
|
|
||||||
|
# GIVEN: A mocked DisplayWindow's show method, a fake screen and relevant settings
|
||||||
|
settings = {
|
||||||
|
'advanced/x11 bypass wm': False,
|
||||||
|
'core/display on monitor': True
|
||||||
|
}
|
||||||
|
mock_settings.value.side_effect = lambda key: settings[key]
|
||||||
|
screen = Screen(1, QtCore.QRect(0, 0, 800, 600), is_display=True)
|
||||||
|
|
||||||
|
# WHEN: A DisplayWindow is created with start_hidden=True
|
||||||
|
DisplayWindow(screen=screen, start_hidden=True)
|
||||||
|
|
||||||
|
# THEN: Window is not shown
|
||||||
|
mocked_show.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
@patch.object(DisplayWindow, 'show')
|
||||||
|
def test_shown_if_start_hidden_is_not_set(mocked_show, display_window_env, mock_settings):
|
||||||
|
"""
|
||||||
|
Tests if DisplayWindow's .show() method is called on constructor if constructed with start_hidden=False
|
||||||
|
"""
|
||||||
|
|
||||||
|
# GIVEN: A mocked DisplayWindow's show method, a fake screen and relevant settings
|
||||||
|
settings = {
|
||||||
|
'advanced/x11 bypass wm': False,
|
||||||
|
'core/display on monitor': True
|
||||||
|
}
|
||||||
|
mock_settings.value.side_effect = lambda key: settings[key]
|
||||||
|
screen = Screen(1, QtCore.QRect(0, 0, 800, 600), is_display=True)
|
||||||
|
|
||||||
|
# WHEN: A DisplayWindow is created with start_hidden=True
|
||||||
|
DisplayWindow(screen=screen, start_hidden=False)
|
||||||
|
|
||||||
|
# THEN: Window is shown
|
||||||
|
mocked_show.assert_called()
|
||||||
|
|
||||||
|
|
||||||
def test_set_scale_not_initialised(display_window_env, mock_settings):
|
def test_set_scale_not_initialised(display_window_env, mock_settings):
|
||||||
"""
|
"""
|
||||||
Test that the scale js is not run if the page is not initialised
|
Test that the scale js is not run if the page is not initialised
|
||||||
|
@ -318,6 +361,27 @@ def test_after_loaded_hide_mouse_not_display(display_window_env, mock_settings):
|
||||||
'});')
|
'});')
|
||||||
|
|
||||||
|
|
||||||
|
def test_after_loaded_callback(display_window_env, mock_settings):
|
||||||
|
"""
|
||||||
|
Test if the __ is loaded on after_loaded() method correctly
|
||||||
|
"""
|
||||||
|
# GIVEN: An initialised display window and settings for item transitions and hide mouse returns true
|
||||||
|
mocked_after_loaded_callback = MagicMock()
|
||||||
|
display_window = DisplayWindow(after_loaded_callback=mocked_after_loaded_callback)
|
||||||
|
display_window.is_display = True
|
||||||
|
mock_settings.value.return_value = True
|
||||||
|
display_window._is_initialised = True
|
||||||
|
display_window.run_javascript = MagicMock()
|
||||||
|
display_window.set_scale = MagicMock()
|
||||||
|
display_window.set_startup_screen = MagicMock()
|
||||||
|
|
||||||
|
# WHEN: after_loaded is run
|
||||||
|
display_window.after_loaded()
|
||||||
|
|
||||||
|
# THEN: The after_loaded_callback should be called
|
||||||
|
mocked_after_loaded_callback.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
@patch.object(time, 'time')
|
@patch.object(time, 'time')
|
||||||
def test_run_javascript_no_sync_no_wait(mock_time, display_window_env, mock_settings):
|
def test_run_javascript_no_sync_no_wait(mock_time, display_window_env, mock_settings):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -771,9 +771,9 @@ def test_screen_changed_modal(mocked_warning, main_window):
|
||||||
|
|
||||||
|
|
||||||
@patch('openlp.core.ui.mainwindow.QtWidgets.QMessageBox.warning')
|
@patch('openlp.core.ui.mainwindow.QtWidgets.QMessageBox.warning')
|
||||||
def test_screen_changed_modal_sets_timestamp_before_blocking_on_modal(mocked_warning, main_window):
|
def test_screen_changed_modal_sets_timestamp_after_blocking_on_modal(mocked_warning, main_window):
|
||||||
"""
|
"""
|
||||||
Test that the screen changed modal latest shown timestamp is set before showing warning message, so
|
Test that the screen changed modal latest shown timestamp is set after showing warning message, so
|
||||||
that duplicate modals due to event spamming on 'config_screen_changed' in less than 5 seconds is mitigated.
|
that duplicate modals due to event spamming on 'config_screen_changed' in less than 5 seconds is mitigated.
|
||||||
"""
|
"""
|
||||||
# GIVEN: a newly opened OpenLP instance, mocked screens, renderer and an special QMessageBox warning handler
|
# GIVEN: a newly opened OpenLP instance, mocked screens, renderer and an special QMessageBox warning handler
|
||||||
|
@ -781,19 +781,13 @@ def test_screen_changed_modal_sets_timestamp_before_blocking_on_modal(mocked_war
|
||||||
main_window._preview_controller = MagicMock()
|
main_window._preview_controller = MagicMock()
|
||||||
main_window._renderer = MagicMock()
|
main_window._renderer = MagicMock()
|
||||||
|
|
||||||
def resets_timestamp(*args, **kwargs):
|
|
||||||
nonlocal main_window
|
|
||||||
main_window.screen_change_timestamp = None
|
|
||||||
|
|
||||||
mocked_warning.side_effect = resets_timestamp
|
|
||||||
|
|
||||||
# WHEN: we trigger a 'config_screen_changed' event
|
# WHEN: we trigger a 'config_screen_changed' event
|
||||||
Registry().execute('config_screen_changed')
|
Registry().execute('config_screen_changed')
|
||||||
|
|
||||||
# THEN: main_window.screen_change_timestamp should be "None", indicating that timestamp is set before
|
# THEN: main_window.screen_change_timestamp should have a timestamp, indicating that timestamp is set after
|
||||||
# the blocking modal is shown.
|
# the blocking modal is shown.
|
||||||
mocked_warning.assert_called_once()
|
mocked_warning.assert_called_once()
|
||||||
assert main_window.screen_change_timestamp is None
|
assert main_window.screen_change_timestamp is not None
|
||||||
|
|
||||||
|
|
||||||
@patch('openlp.core.ui.mainwindow.QtWidgets.QMessageBox.critical')
|
@patch('openlp.core.ui.mainwindow.QtWidgets.QMessageBox.critical')
|
||||||
|
|
|
@ -1134,6 +1134,61 @@ def test_process_item_song_no_vlc(mocked_execute, registry, state_media):
|
||||||
assert 2 == slide_controller.preview_display.load_verses.call_count, 'Execute should have been called 2 times'
|
assert 2 == slide_controller.preview_display.load_verses.call_count, 'Execute should have been called 2 times'
|
||||||
|
|
||||||
|
|
||||||
|
@patch.object(Registry, 'execute')
|
||||||
|
def test_process_item_is_reloading_wont_change_display_hide_mode(mocked_execute, registry, state_media):
|
||||||
|
"""
|
||||||
|
Test if the display's hide mode is not changed when using is_reloading parameter
|
||||||
|
"""
|
||||||
|
# GIVEN: A mocked presentation service item, a mocked media service item, a mocked Registry.execute
|
||||||
|
# and a slide controller with many mocks.
|
||||||
|
# and the setting 'themes/item transitions' = True
|
||||||
|
mocked_media_item = MagicMock()
|
||||||
|
mocked_media_item.name = 'mocked_media_item'
|
||||||
|
mocked_media_item.get_transition_delay.return_value = 0
|
||||||
|
mocked_media_item.is_text.return_value = True
|
||||||
|
mocked_media_item.is_command.return_value = False
|
||||||
|
mocked_media_item.is_media.return_value = False
|
||||||
|
mocked_media_item.requires_media.return_value = False
|
||||||
|
mocked_media_item.is_image.return_value = False
|
||||||
|
mocked_media_item.from_service = False
|
||||||
|
mocked_media_item.get_frames.return_value = []
|
||||||
|
mocked_media_item.display_slides = [{'verse': 'Verse name'}]
|
||||||
|
mocked_settings = MagicMock()
|
||||||
|
mocked_settings.value.return_value = True
|
||||||
|
mocked_main_window = MagicMock()
|
||||||
|
Registry().register('main_window', mocked_main_window)
|
||||||
|
Registry().register('media_controller', MagicMock())
|
||||||
|
Registry().register('application', MagicMock())
|
||||||
|
Registry().register('settings', mocked_settings)
|
||||||
|
slide_controller = SlideController(None)
|
||||||
|
slide_controller.service_item = None
|
||||||
|
slide_controller.is_live = True
|
||||||
|
slide_controller._reset_blank = MagicMock()
|
||||||
|
slide_controller.preview_widget = MagicMock()
|
||||||
|
slide_controller.preview_display = MagicMock()
|
||||||
|
slide_controller.enable_tool_bar = MagicMock()
|
||||||
|
slide_controller.on_controller_size_changed = MagicMock()
|
||||||
|
slide_controller.on_media_start = MagicMock()
|
||||||
|
slide_controller.on_media_close = MagicMock()
|
||||||
|
slide_controller.slide_selected = MagicMock()
|
||||||
|
slide_controller.set_hide_mode = MagicMock()
|
||||||
|
slide_controller.new_song_menu = MagicMock()
|
||||||
|
slide_controller.on_stop_loop = MagicMock()
|
||||||
|
slide_controller.info_label = MagicMock()
|
||||||
|
slide_controller.song_menu = MagicMock()
|
||||||
|
slide_controller.displays = [MagicMock()]
|
||||||
|
slide_controller.toolbar = MagicMock()
|
||||||
|
slide_controller.split = 0
|
||||||
|
slide_controller.type_prefix = 'test'
|
||||||
|
slide_controller.screen_capture = 'old_capture'
|
||||||
|
|
||||||
|
# WHEN: _process_item is called with is_reloading=True
|
||||||
|
slide_controller._process_item(mocked_media_item, 0, is_reloading=True)
|
||||||
|
|
||||||
|
# THEN: set_hide_mode should not be called
|
||||||
|
slide_controller.set_hide_mode.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_live_stolen_focus_shortcuts(settings):
|
def test_live_stolen_focus_shortcuts(settings):
|
||||||
"""
|
"""
|
||||||
Test that all the needed shortcuts are available in scenarios where Live has stolen focus.
|
Test that all the needed shortcuts are available in scenarios where Live has stolen focus.
|
||||||
|
|
Loading…
Reference in New Issue