def init_transition(self, window_count: int, blur: Optional[Transition], unblur: Optional[Transition]) -> Tuple: """ Initiate a blur or unblur transition depending on the given number of windows on the current workspace, and only if the previously started transition was in the opposite direction. Transitions can only be started alternately, so an unblur one may only occur after a blur transition and vice versa, regardless of whether the previous transition is finished. :param window_count: The number of open windows :param blur: The previous blur transition or None :param unblur: The previous unblur transition or None :return: The current transition threads """ # Blur if window_count >= self.window_threshold and unblur is not None: unblur.stop() blur = Transition(unblur.current_level, self.transition_steps) blur.start() unblur = None # Unblur if window_count < self.window_threshold and blur is not None: blur.stop() unblur = Transition(blur.current_level, 0) unblur.start() blur = None return blur, unblur
def test_init_transition_blurs_when_over_threshold(mocker): args = Namespace(min=2, steps=10, blur=0, ignore=[]) blur = Blur(args) blur_thread = Transition(0, 0) unblur_thread = Transition(0, 0) mock_transition = mocker.patch('blurwal.blur.Transition') blur.init_transition(2, blur_thread, unblur_thread) mock_transition.assert_called_once_with(0, 10)
def test_init_transition_unblurs_when_under_threshold(mocker): args = Namespace(min=2, steps=10, blur=0, ignore=[]) blur = Blur(args) blur_thread = Transition(0, 0) blur_thread.current_level = 10 # Blur thread has completed unblur_thread = Transition(0, 0) mock_transition = mocker.patch('blurwal.blur.Transition') blur.init_transition(0, blur_thread, unblur_thread) mock_transition.assert_called_once_with(10, 0)
def test_init_transition_does_not_unblur_consecutively(mocker): mocker.patch('blurwal.wallpaper.change_to') args = Namespace(min=2, steps=10, blur=0, ignore=[]) blur = Blur(args) # Unblur as previous transition blur_thread, unblur_thread = blur.init_transition(0, Transition(0, 0), Transition(0, 0)) mock_transition = mocker.patch('blurwal.blur.Transition') # Should not unblur again consecutively blur.init_transition(0, blur_thread, unblur_thread) mock_transition.assert_not_called()
def listen_for_events(self) -> None: """ Listen for X11 events covering window creation and movement between workspaces and, upon receiving such an event, count the number of windows on the currently focused workspace. If the number of open windows is equal to or above the set threshold, initiate a blur, otherwise an unblur transition. The following events are monitored and should be enough to cover any situation in which a blur operation is necessary: MapNotify is sent when windows are drawn, e.g. a window - is opened on the current workspace - is moved to the current workspace - is shown by switching to the workspace it's on UnmapNotify is sent when windows are undrawn, e.g. a window - on the current workspace is closed - is moved to a different workspace - is hidden by switching to a different workspace :return: None """ # Connect to X server display = Xlib.display.Display() ewmh_instance = ewmh.EWMH(display) root = display.screen().root root.change_attributes(event_mask=X.SubstructureNotifyMask) print(':: Ready and waiting for window events...') blur = Transition(0, 0) unblur = Transition(0, 0) while True: event = display.next_event() if event.type in (X.MapNotify, X.UnmapNotify): if wallpaper.changed_externally(): wallpaper.set_original(wallpaper.get_current()) if self.frames_are_outdated(): self.generate_transition_frames() window_count = window.count_on_current_ws( self.ignored_classes, ewmh_instance) blur, unblur = self.init_transition(window_count, blur, unblur)
def test_stop_cancels_transition(mock_change_to): thread = Transition(0, 10) thread.start() thread.stop() assert thread.is_stopped() assert mock_change_to.call_count == 1
def test_run_unblur(mock_change_to): thread = Transition(8, 2) thread.start() thread.join() # Wait for thread completion assert mock_change_to.call_count == 6