From 12fd5b2341331bfef449d5589dd430e52ad95732 Mon Sep 17 00:00:00 2001 From: lars-berger Date: Thu, 14 Sep 2023 01:01:46 +0800 Subject: [PATCH] feat: reduce amount of calls to set native focus (#390) --- GlazeWM.App.WindowManager/WmStartup.cs | 25 ++++++------- .../WorkspacesComponentViewModel.cs | 1 + .../PopulateInitialStateHandler.cs | 10 +++--- GlazeWM.Domain/Common/DomainEvent.cs | 2 +- .../FocusInDirectionHandler.cs | 4 ++- ...usHandler.cs => SyncNativeFocusHandler.cs} | 36 ++++++++++--------- .../CommandHandlers/ToggleFocusModeHandler.cs | 3 +- .../Commands/SetNativeFocusCommand.cs | 14 -------- .../Commands/SyncNativeFocusCommand.cs | 8 +++++ GlazeWM.Domain/Containers/ContainerService.cs | 5 +++ .../Events/NativeFocusReassignedEvent.cs | 8 ----- .../Events/NativeFocusSyncedEvent.cs | 8 +++++ GlazeWM.Domain/DependencyInjection.cs | 2 +- .../RegisterKeybindingsHandler.cs | 1 + .../CommandHandlers/ManageWindowHandler.cs | 4 +-- .../CommandHandlers/MoveWindowHandler.cs | 4 --- .../CommandHandlers/ResizeWindowHandler.cs | 1 - .../CommandHandlers/UnmanageWindowHandler.cs | 3 +- .../EventHandlers/WindowDestroyedHandler.cs | 1 + .../EventHandlers/WindowFocusedHandler.cs | 13 ++++--- .../EventHandlers/WindowHiddenHandler.cs | 1 + .../EventHandlers/WindowMinimizedHandler.cs | 6 ++-- .../EventHandlers/WindowShownHandler.cs | 1 + .../CommandHandlers/FocusWorkspaceHandler.cs | 4 +-- .../MoveWindowToWorkspaceHandler.cs | 2 +- 25 files changed, 88 insertions(+), 79 deletions(-) rename GlazeWM.Domain/Containers/CommandHandlers/{SetNativeFocusHandler.cs => SyncNativeFocusHandler.cs} (51%) delete mode 100644 GlazeWM.Domain/Containers/Commands/SetNativeFocusCommand.cs create mode 100644 GlazeWM.Domain/Containers/Commands/SyncNativeFocusCommand.cs delete mode 100644 GlazeWM.Domain/Containers/Events/NativeFocusReassignedEvent.cs create mode 100644 GlazeWM.Domain/Containers/Events/NativeFocusSyncedEvent.cs diff --git a/GlazeWM.App.WindowManager/WmStartup.cs b/GlazeWM.App.WindowManager/WmStartup.cs index 5200efc3a..78488316f 100644 --- a/GlazeWM.App.WindowManager/WmStartup.cs +++ b/GlazeWM.App.WindowManager/WmStartup.cs @@ -49,6 +49,7 @@ public ExitCode Run() // Populate initial monitors, windows, workspaces and user config. _bus.Invoke(new PopulateInitialStateCommand()); _bus.Invoke(new RedrawContainersCommand()); + _bus.Invoke(new SyncNativeFocusCommand()); // Listen on registered keybindings. _keybindingService.Start(); @@ -75,22 +76,14 @@ public ExitCode Run() _systemTrayIcon = new SystemTrayIcon(systemTrayIconConfig); _systemTrayIcon.Show(); - var nativeFocusReassigned = _bus.Events - .OfType() - .Select((@event) => @event.FocusedContainer); - if (_userConfigService.FocusBorderConfig.Active.Enabled || _userConfigService.FocusBorderConfig.Inactive.Enabled) { - var focusChanged = _bus.Events - .OfType() - .Select(@event => @event.FocusedContainer); - - focusChanged - .Merge(nativeFocusReassigned) - .Subscribe((container) => - _bus.InvokeAsync(new SetActiveWindowBorderCommand(container as Window)) - ); + _bus.Events.OfType().Subscribe((@event) => + _bus.InvokeAsync( + new SetActiveWindowBorderCommand(@event.FocusedContainer as Window) + ) + ); } // Hook mouse event for focus follows cursor. @@ -108,7 +101,11 @@ public ExitCode Run() .OfType() .Select(@event => @event.FocusedContainer); - focusedContainerMoved.Merge(nativeFocusReassigned) + var nativeFocusSynced = _bus.Events + .OfType() + .Select((@event) => @event.FocusedContainer); + + focusedContainerMoved.Merge(nativeFocusSynced) .Where(container => container is Window) .Subscribe((window) => _bus.InvokeAsync(new CenterCursorOnContainerCommand(window))); } diff --git a/GlazeWM.Bar/Components/WorkspacesComponentViewModel.cs b/GlazeWM.Bar/Components/WorkspacesComponentViewModel.cs index 0929e8a93..772be35c4 100644 --- a/GlazeWM.Bar/Components/WorkspacesComponentViewModel.cs +++ b/GlazeWM.Bar/Components/WorkspacesComponentViewModel.cs @@ -78,6 +78,7 @@ public WorkspacesComponentViewModel( @event is WorkspaceActivatedEvent or WorkspaceDeactivatedEvent or FocusChangedEvent + or FocusedContainerMovedEvent ); // Refresh contents of workspaces collection. diff --git a/GlazeWM.Domain/Common/CommandHandlers/PopulateInitialStateHandler.cs b/GlazeWM.Domain/Common/CommandHandlers/PopulateInitialStateHandler.cs index fbce59374..a2df4969a 100644 --- a/GlazeWM.Domain/Common/CommandHandlers/PopulateInitialStateHandler.cs +++ b/GlazeWM.Domain/Common/CommandHandlers/PopulateInitialStateHandler.cs @@ -2,7 +2,6 @@ using GlazeWM.Domain.Common.Commands; using GlazeWM.Domain.Containers; using GlazeWM.Domain.Containers.Commands; -using GlazeWM.Domain.Containers.Events; using GlazeWM.Domain.Monitors; using GlazeWM.Domain.Monitors.Commands; using GlazeWM.Domain.UserConfigs.Commands; @@ -17,16 +16,20 @@ namespace GlazeWM.Domain.Common.CommandHandlers internal sealed class PopulateInitialStateHandler : ICommandHandler { private readonly Bus _bus; + private readonly ContainerService _containerService; private readonly MonitorService _monitorService; private readonly WindowService _windowService; private readonly WorkspaceService _workspaceService; - public PopulateInitialStateHandler(Bus bus, + public PopulateInitialStateHandler( + Bus bus, + ContainerService containerService, MonitorService monitorService, WindowService windowService, WorkspaceService workspaceService) { _bus = bus; + _containerService = containerService; _monitorService = monitorService; _windowService = windowService; _workspaceService = workspaceService; @@ -58,8 +61,7 @@ public CommandResponse Handle(PopulateInitialStateCommand command) _workspaceService.GetActiveWorkspaces().FirstOrDefault() as Container; _bus.Invoke(new SetFocusedDescendantCommand(containerToFocus)); - _bus.Emit(new FocusChangedEvent(containerToFocus)); - _bus.Invoke(new SetNativeFocusCommand(containerToFocus)); + _containerService.HasPendingFocusSync = true; return CommandResponse.Ok; } diff --git a/GlazeWM.Domain/Common/DomainEvent.cs b/GlazeWM.Domain/Common/DomainEvent.cs index a5291668d..7eb80e458 100644 --- a/GlazeWM.Domain/Common/DomainEvent.cs +++ b/GlazeWM.Domain/Common/DomainEvent.cs @@ -7,7 +7,7 @@ public static class DomainEvent public const string FocusedContainerMoved = "focused_container_moved"; public const string MonitorAdded = "monitor_added"; public const string MonitorRemoved = "monitor_removed"; - public const string NativeFocusReassigned = "native_focus_reassigned"; + public const string NativeFocusSynced = "native_focus_synced"; public const string TilingDirectionChanged = "tiling_direction_changed"; public const string UserConfigReloaded = "user_config_reloaded"; public const string WindowManaged = "window_managed"; diff --git a/GlazeWM.Domain/Containers/CommandHandlers/FocusInDirectionHandler.cs b/GlazeWM.Domain/Containers/CommandHandlers/FocusInDirectionHandler.cs index 834d55701..0e79d7522 100644 --- a/GlazeWM.Domain/Containers/CommandHandlers/FocusInDirectionHandler.cs +++ b/GlazeWM.Domain/Containers/CommandHandlers/FocusInDirectionHandler.cs @@ -34,7 +34,9 @@ public CommandResponse Handle(FocusInDirectionCommand command) if (focusTarget is null || focusTarget == focusedContainer) return CommandResponse.Ok; - _bus.Invoke(new SetNativeFocusCommand(focusTarget)); + _bus.Invoke(new SetFocusedDescendantCommand(focusTarget)); + _containerService.HasPendingFocusSync = true; + return CommandResponse.Ok; } diff --git a/GlazeWM.Domain/Containers/CommandHandlers/SetNativeFocusHandler.cs b/GlazeWM.Domain/Containers/CommandHandlers/SyncNativeFocusHandler.cs similarity index 51% rename from GlazeWM.Domain/Containers/CommandHandlers/SetNativeFocusHandler.cs rename to GlazeWM.Domain/Containers/CommandHandlers/SyncNativeFocusHandler.cs index e8dbf9b8d..26cff51a5 100644 --- a/GlazeWM.Domain/Containers/CommandHandlers/SetNativeFocusHandler.cs +++ b/GlazeWM.Domain/Containers/CommandHandlers/SyncNativeFocusHandler.cs @@ -8,22 +8,33 @@ namespace GlazeWM.Domain.Containers.CommandHandlers { - internal sealed class SetNativeFocusHandler : ICommandHandler + internal sealed class SyncNativeFocusHandler : ICommandHandler { private readonly Bus _bus; + private readonly ContainerService _containerService; private readonly WindowService _windowService; - public SetNativeFocusHandler(Bus bus, WindowService windowService) + public SyncNativeFocusHandler( + Bus bus, + ContainerService containerService, + WindowService windowService) { _bus = bus; + _containerService = containerService; _windowService = windowService; } - public CommandResponse Handle(SetNativeFocusCommand command) + public CommandResponse Handle(SyncNativeFocusCommand command) { - var containerToFocus = command.ContainerToFocus; + var hasPendingFocusSync = _containerService.HasPendingFocusSync; - var handleToFocus = containerToFocus switch + if (!hasPendingFocusSync) + return CommandResponse.Ok; + + // Container that the WM believes should have focus. + var focusedContainer = _containerService.FocusedContainer; + + var handleToFocus = focusedContainer switch { Window window => window.Handle, Workspace => _windowService.DesktopWindowHandle, @@ -31,21 +42,12 @@ public CommandResponse Handle(SetNativeFocusCommand command) }; // Set focus to the given window handle. If the container is a normal window, then this - // will trigger `EVENT_SYSTEM_FOREGROUND` window event and its handler. This, in turn, - // calls `SetFocusedDescendantCommand`. + // will trigger `EVENT_SYSTEM_FOREGROUND` window event and its handler. KeybdEvent(0, 0, 0, 0); SetForegroundWindow(handleToFocus); - _bus.Emit(new NativeFocusReassignedEvent(containerToFocus)); - - // Setting focus to the desktop window does not emit `EVENT_SYSTEM_FOREGROUND` window event, - // so `SetFocusedDescendantCommand` has to be manually called. - // TODO: This is called twice unnecessarily when setting workspace focus on unmanage. - if (containerToFocus is Workspace) - { - _bus.Invoke(new SetFocusedDescendantCommand(containerToFocus)); - _bus.Emit(new FocusChangedEvent(containerToFocus)); - } + _bus.Emit(new NativeFocusSyncedEvent(focusedContainer)); + _bus.Emit(new FocusChangedEvent(focusedContainer)); return CommandResponse.Ok; } diff --git a/GlazeWM.Domain/Containers/CommandHandlers/ToggleFocusModeHandler.cs b/GlazeWM.Domain/Containers/CommandHandlers/ToggleFocusModeHandler.cs index 366c6b613..a0e18b3da 100644 --- a/GlazeWM.Domain/Containers/CommandHandlers/ToggleFocusModeHandler.cs +++ b/GlazeWM.Domain/Containers/CommandHandlers/ToggleFocusModeHandler.cs @@ -34,7 +34,8 @@ public CommandResponse Handle(ToggleFocusModeCommand command) if (windowToFocus is null) return CommandResponse.Ok; - _bus.Invoke(new SetNativeFocusCommand(windowToFocus)); + _bus.Invoke(new SetFocusedDescendantCommand(windowToFocus)); + _containerService.HasPendingFocusSync = true; return CommandResponse.Ok; } diff --git a/GlazeWM.Domain/Containers/Commands/SetNativeFocusCommand.cs b/GlazeWM.Domain/Containers/Commands/SetNativeFocusCommand.cs deleted file mode 100644 index d5a847891..000000000 --- a/GlazeWM.Domain/Containers/Commands/SetNativeFocusCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using GlazeWM.Infrastructure.Bussing; - -namespace GlazeWM.Domain.Containers.Commands -{ - public class SetNativeFocusCommand : Command - { - public Container ContainerToFocus { get; } - - public SetNativeFocusCommand(Container containerToFocus) - { - ContainerToFocus = containerToFocus; - } - } -} diff --git a/GlazeWM.Domain/Containers/Commands/SyncNativeFocusCommand.cs b/GlazeWM.Domain/Containers/Commands/SyncNativeFocusCommand.cs new file mode 100644 index 000000000..7f52faf99 --- /dev/null +++ b/GlazeWM.Domain/Containers/Commands/SyncNativeFocusCommand.cs @@ -0,0 +1,8 @@ +using GlazeWM.Infrastructure.Bussing; + +namespace GlazeWM.Domain.Containers.Commands +{ + public class SyncNativeFocusCommand : Command + { + } +} diff --git a/GlazeWM.Domain/Containers/ContainerService.cs b/GlazeWM.Domain/Containers/ContainerService.cs index 6bbd7d32d..e7b68ed0d 100644 --- a/GlazeWM.Domain/Containers/ContainerService.cs +++ b/GlazeWM.Domain/Containers/ContainerService.cs @@ -28,6 +28,11 @@ public class ContainerService /// public Container FocusedContainer => ContainerTree.LastFocusedDescendant; + /// + /// Whether native focus needs to be reassigned to `FocusedContainer`. + /// + public bool HasPendingFocusSync { get; set; } + /// /// Whether a tiling or floating container is currently focused. /// diff --git a/GlazeWM.Domain/Containers/Events/NativeFocusReassignedEvent.cs b/GlazeWM.Domain/Containers/Events/NativeFocusReassignedEvent.cs deleted file mode 100644 index 7c1795d07..000000000 --- a/GlazeWM.Domain/Containers/Events/NativeFocusReassignedEvent.cs +++ /dev/null @@ -1,8 +0,0 @@ -using GlazeWM.Domain.Common; -using GlazeWM.Infrastructure.Bussing; - -namespace GlazeWM.Domain.Containers.Events -{ - public record NativeFocusReassignedEvent(Container FocusedContainer) - : Event(DomainEvent.NativeFocusReassigned); -} diff --git a/GlazeWM.Domain/Containers/Events/NativeFocusSyncedEvent.cs b/GlazeWM.Domain/Containers/Events/NativeFocusSyncedEvent.cs new file mode 100644 index 000000000..7c59f9c47 --- /dev/null +++ b/GlazeWM.Domain/Containers/Events/NativeFocusSyncedEvent.cs @@ -0,0 +1,8 @@ +using GlazeWM.Domain.Common; +using GlazeWM.Infrastructure.Bussing; + +namespace GlazeWM.Domain.Containers.Events +{ + public record NativeFocusSyncedEvent(Container FocusedContainer) + : Event(DomainEvent.NativeFocusSynced); +} diff --git a/GlazeWM.Domain/DependencyInjection.cs b/GlazeWM.Domain/DependencyInjection.cs index 293d0c607..2180e2ebe 100644 --- a/GlazeWM.Domain/DependencyInjection.cs +++ b/GlazeWM.Domain/DependencyInjection.cs @@ -52,7 +52,7 @@ public static IServiceCollection AddDomainServices(this IServiceCollection servi services.AddSingleton, ReplaceContainerHandler>(); services.AddSingleton, ResizeContainerHandler>(); services.AddSingleton, SetFocusedDescendantHandler>(); - services.AddSingleton, SetNativeFocusHandler>(); + services.AddSingleton, SyncNativeFocusHandler>(); services.AddSingleton, ToggleFocusModeHandler>(); services.AddSingleton, AddMonitorHandler>(); services.AddSingleton, RefreshMonitorStateHandler>(); diff --git a/GlazeWM.Domain/UserConfigs/CommandHandlers/RegisterKeybindingsHandler.cs b/GlazeWM.Domain/UserConfigs/CommandHandlers/RegisterKeybindingsHandler.cs index f2eb2de85..a6fc2f543 100644 --- a/GlazeWM.Domain/UserConfigs/CommandHandlers/RegisterKeybindingsHandler.cs +++ b/GlazeWM.Domain/UserConfigs/CommandHandlers/RegisterKeybindingsHandler.cs @@ -54,6 +54,7 @@ public CommandResponse Handle(RegisterKeybindingsCommand command) _bus.Invoke(new RunWithSubjectContainerCommand(commandStrings)); _bus.Invoke(new RedrawContainersCommand()); + _bus.Invoke(new SyncNativeFocusCommand()); } } catch (Exception e) diff --git a/GlazeWM.Domain/Windows/CommandHandlers/ManageWindowHandler.cs b/GlazeWM.Domain/Windows/CommandHandlers/ManageWindowHandler.cs index 7e722f77b..8c03d8295 100644 --- a/GlazeWM.Domain/Windows/CommandHandlers/ManageWindowHandler.cs +++ b/GlazeWM.Domain/Windows/CommandHandlers/ManageWindowHandler.cs @@ -85,8 +85,8 @@ public CommandResponse Handle(ManageWindowCommand command) _logger.LogWindowEvent("New window managed", window); _bus.Emit(new WindowManagedEvent(window)); - // Set OS focus to the newly added window in case it's not already focused. - _bus.Invoke(new SetNativeFocusCommand(window)); + // OS focus should be set to the newly added window in case it's not already focused. + _containerService.HasPendingFocusSync = true; return CommandResponse.Ok; } diff --git a/GlazeWM.Domain/Windows/CommandHandlers/MoveWindowHandler.cs b/GlazeWM.Domain/Windows/CommandHandlers/MoveWindowHandler.cs index 6b477b5ea..220a1c626 100644 --- a/GlazeWM.Domain/Windows/CommandHandlers/MoveWindowHandler.cs +++ b/GlazeWM.Domain/Windows/CommandHandlers/MoveWindowHandler.cs @@ -128,9 +128,6 @@ private void MoveToWorkspaceInDirection(Window windowToMove, Direction direction _bus.Invoke(new MoveContainerWithinTreeCommand(windowToMove, workspaceInDirection, true)); else _bus.Invoke(new MoveContainerWithinTreeCommand(windowToMove, workspaceInDirection, 0, true)); - - // Refresh state in bar of which workspace has focus. - _bus.Emit(new FocusChangedEvent(windowToMove)); } private void ChangeWorkspaceTilingDirection(Window windowToMove, Direction direction) @@ -289,7 +286,6 @@ private void MoveFloatingWindow(Window windowToMove, Direction direction) // Change the window's parent workspace. _bus.Invoke(new MoveContainerWithinTreeCommand(windowToMove, workspaceInDirection, false)); - _bus.Emit(new FocusChangedEvent(windowToMove)); // Redrawing twice to fix weird WindowsOS dpi behaviour windowToMove.HasPendingDpiAdjustment = true; diff --git a/GlazeWM.Domain/Windows/CommandHandlers/ResizeWindowHandler.cs b/GlazeWM.Domain/Windows/CommandHandlers/ResizeWindowHandler.cs index a32463f34..ff8f555a8 100644 --- a/GlazeWM.Domain/Windows/CommandHandlers/ResizeWindowHandler.cs +++ b/GlazeWM.Domain/Windows/CommandHandlers/ResizeWindowHandler.cs @@ -131,7 +131,6 @@ private void ResizeFloatingWindow(Window windowToResize, ResizeDimension dimensi // Change the window's parent workspace. _bus.Invoke(new MoveContainerWithinTreeCommand(windowToResize, targetWorkspace, false)); - _bus.Emit(new FocusChangedEvent(windowToResize)); windowToResize.HasPendingDpiAdjustment = true; } diff --git a/GlazeWM.Domain/Windows/CommandHandlers/UnmanageWindowHandler.cs b/GlazeWM.Domain/Windows/CommandHandlers/UnmanageWindowHandler.cs index ff88e2f77..5e2b56b14 100644 --- a/GlazeWM.Domain/Windows/CommandHandlers/UnmanageWindowHandler.cs +++ b/GlazeWM.Domain/Windows/CommandHandlers/UnmanageWindowHandler.cs @@ -34,8 +34,9 @@ public CommandResponse Handle(UnmanageWindowCommand command) // cause focus to briefly flicker to the OS focus target and then to the WM's focus // target. + _bus.Invoke(new SetFocusedDescendantCommand(focusTarget)); _containerService.PendingFocusContainer = focusTarget; - _bus.InvokeAsync(new SetNativeFocusCommand(focusTarget)); + _containerService.HasPendingFocusSync = true; _bus.Emit(new WindowUnmanagedEvent(window.Id, window.Handle)); diff --git a/GlazeWM.Domain/Windows/EventHandlers/WindowDestroyedHandler.cs b/GlazeWM.Domain/Windows/EventHandlers/WindowDestroyedHandler.cs index 2c318b517..63cc3857e 100644 --- a/GlazeWM.Domain/Windows/EventHandlers/WindowDestroyedHandler.cs +++ b/GlazeWM.Domain/Windows/EventHandlers/WindowDestroyedHandler.cs @@ -47,6 +47,7 @@ public void Handle(WindowDestroyedEvent @event) // If window is in tree, detach the removed window from its parent. _bus.Invoke(new UnmanageWindowCommand(window)); _bus.Invoke(new RedrawContainersCommand()); + _bus.Invoke(new SyncNativeFocusCommand()); } } } diff --git a/GlazeWM.Domain/Windows/EventHandlers/WindowFocusedHandler.cs b/GlazeWM.Domain/Windows/EventHandlers/WindowFocusedHandler.cs index 5be8315c5..02b891d74 100644 --- a/GlazeWM.Domain/Windows/EventHandlers/WindowFocusedHandler.cs +++ b/GlazeWM.Domain/Windows/EventHandlers/WindowFocusedHandler.cs @@ -4,11 +4,9 @@ using GlazeWM.Domain.Containers.Commands; using GlazeWM.Domain.Containers.Events; using GlazeWM.Domain.Workspaces; -using GlazeWM.Domain.Workspaces.Commands; using GlazeWM.Infrastructure.Bussing; using GlazeWM.Infrastructure.Common.Events; using Microsoft.Extensions.Logging; -using static GlazeWM.Infrastructure.WindowsApi.WindowsApiService; namespace GlazeWM.Domain.Windows.EventHandlers { @@ -61,7 +59,7 @@ public void Handle(WindowFocusedEvent @event) return; } - _bus.InvokeAsync(new SetNativeFocusCommand(pendingFocusContainer)); + _bus.InvokeAsync(new SyncNativeFocusCommand()); return; } @@ -71,8 +69,15 @@ public void Handle(WindowFocusedEvent @event) if (window is null || window?.IsDisplayed == false) return; - _logger.LogWindowEvent("Window focused", window); + _logger.LogWindowEvent("Native focus event", window); + var focusedContainer = _containerService.FocusedContainer; + + // Focus is already set to the WM's focused container. + if (window == focusedContainer) + return; + + // Update the WM's focus state. _bus.Invoke(new SetFocusedDescendantCommand(window)); _bus.Emit(new FocusChangedEvent(window)); } diff --git a/GlazeWM.Domain/Windows/EventHandlers/WindowHiddenHandler.cs b/GlazeWM.Domain/Windows/EventHandlers/WindowHiddenHandler.cs index 47c36430c..e7db591a0 100644 --- a/GlazeWM.Domain/Windows/EventHandlers/WindowHiddenHandler.cs +++ b/GlazeWM.Domain/Windows/EventHandlers/WindowHiddenHandler.cs @@ -50,6 +50,7 @@ public void Handle(WindowHiddenEvent @event) // Detach the hidden window from its parent. _bus.Invoke(new UnmanageWindowCommand(window)); _bus.Invoke(new RedrawContainersCommand()); + _bus.Invoke(new SyncNativeFocusCommand()); } } } diff --git a/GlazeWM.Domain/Windows/EventHandlers/WindowMinimizedHandler.cs b/GlazeWM.Domain/Windows/EventHandlers/WindowMinimizedHandler.cs index dfdb097c8..75e4b02fa 100644 --- a/GlazeWM.Domain/Windows/EventHandlers/WindowMinimizedHandler.cs +++ b/GlazeWM.Domain/Windows/EventHandlers/WindowMinimizedHandler.cs @@ -60,11 +60,13 @@ public void Handle(WindowMinimizedEvent @event) _bus.Invoke(new ReplaceContainerCommand(minimizedWindow, window.Parent, window.Index)); - // Reassign focus to appropriate container. - _bus.InvokeAsync(new SetNativeFocusCommand(focusTarget)); + // Focus should be reassigned to appropriate container. + _bus.Invoke(new SetFocusedDescendantCommand(focusTarget)); + _containerService.HasPendingFocusSync = true; _containerService.ContainersToRedraw.Add(workspace); _bus.Invoke(new RedrawContainersCommand()); + _bus.Invoke(new SyncNativeFocusCommand()); } } } diff --git a/GlazeWM.Domain/Windows/EventHandlers/WindowShownHandler.cs b/GlazeWM.Domain/Windows/EventHandlers/WindowShownHandler.cs index e300e1243..410b1e9cb 100644 --- a/GlazeWM.Domain/Windows/EventHandlers/WindowShownHandler.cs +++ b/GlazeWM.Domain/Windows/EventHandlers/WindowShownHandler.cs @@ -38,6 +38,7 @@ public void Handle(WindowShownEvent @event) _bus.Invoke(new ManageWindowCommand(@event.WindowHandle)); _bus.Invoke(new RedrawContainersCommand()); + _bus.Invoke(new SyncNativeFocusCommand()); } } } diff --git a/GlazeWM.Domain/Workspaces/CommandHandlers/FocusWorkspaceHandler.cs b/GlazeWM.Domain/Workspaces/CommandHandlers/FocusWorkspaceHandler.cs index 8e5239ce8..680708800 100644 --- a/GlazeWM.Domain/Workspaces/CommandHandlers/FocusWorkspaceHandler.cs +++ b/GlazeWM.Domain/Workspaces/CommandHandlers/FocusWorkspaceHandler.cs @@ -67,7 +67,7 @@ public CommandResponse Handle(FocusWorkspaceCommand command) : workspaceToFocus; _bus.Invoke(new SetFocusedDescendantCommand(containerToFocus)); - _bus.Emit(new FocusChangedEvent(containerToFocus)); + _containerService.HasPendingFocusSync = true; // Display the workspace to switch focus to. if (focusedWorkspace.Parent == workspaceToFocus.Parent) @@ -76,8 +76,6 @@ public CommandResponse Handle(FocusWorkspaceCommand command) _containerService.ContainersToRedraw.Add(workspaceToFocus); } - _bus.Invoke(new SetNativeFocusCommand(containerToFocus)); - // Get empty workspace to destroy (if any are found). Cannot destroy empty workspaces if // they're the only workspace on the monitor or are pending focus. var workspaceToDestroy = _workspaceService diff --git a/GlazeWM.Domain/Workspaces/CommandHandlers/MoveWindowToWorkspaceHandler.cs b/GlazeWM.Domain/Workspaces/CommandHandlers/MoveWindowToWorkspaceHandler.cs index a5e74c229..a4ab961d0 100644 --- a/GlazeWM.Domain/Workspaces/CommandHandlers/MoveWindowToWorkspaceHandler.cs +++ b/GlazeWM.Domain/Workspaces/CommandHandlers/MoveWindowToWorkspaceHandler.cs @@ -64,7 +64,7 @@ public CommandResponse Handle(MoveWindowToWorkspaceCommand command) // immediately afterwards and they should behave as if `focusTarget` is the focused // descendant. _bus.Invoke(new SetFocusedDescendantCommand(focusTarget)); - _bus.Invoke(new SetNativeFocusCommand(focusTarget)); + _containerService.HasPendingFocusSync = true; _containerService.ContainersToRedraw.Add(currentWorkspace); _containerService.ContainersToRedraw.Add(windowToMove);