diff --git a/GlazeWM.Domain/Containers/CommandHandlers/RedrawContainersHandler.cs b/GlazeWM.Domain/Containers/CommandHandlers/RedrawContainersHandler.cs index dc051aae0..f8dc68770 100644 --- a/GlazeWM.Domain/Containers/CommandHandlers/RedrawContainersHandler.cs +++ b/GlazeWM.Domain/Containers/CommandHandlers/RedrawContainersHandler.cs @@ -70,8 +70,8 @@ private void SetWindowPosition(Window window) SetWindowPosFlags.FrameChanged | SetWindowPosFlags.NoActivate | SetWindowPosFlags.NoCopyBits | - SetWindowPosFlags.NoSendChanging; - // SetWindowPosFlags.AsyncWindowPos; + SetWindowPosFlags.NoSendChanging | + SetWindowPosFlags.AsyncWindowPos; var workspace = window.Ancestors.OfType().First(); var isWorkspaceDisplayed = workspace.IsDisplayed; diff --git a/GlazeWM.Domain/Windows/EventHandlers/WindowFocusedHandler.cs b/GlazeWM.Domain/Windows/EventHandlers/WindowFocusedHandler.cs index 6c2612038..746b4df1a 100644 --- a/GlazeWM.Domain/Windows/EventHandlers/WindowFocusedHandler.cs +++ b/GlazeWM.Domain/Windows/EventHandlers/WindowFocusedHandler.cs @@ -68,18 +68,24 @@ public void Handle(WindowFocusedEvent @event) var window = _windowService.GetWindows() .FirstOrDefault(window => window.Handle == @event.WindowHandle); - if (window is null) + if (window is null || window.DisplayState != DisplayState.Shown) + // if (window is null || window.DisplayState is DisplayState.Hidden) return; + // if (window is null) + // return; + // TODO: Need to return early for other display states. // TODO: Should this be moved to `WindowShownHandler`. Is show event // emitted first, or foreground? - if (window.DisplayState is DisplayState.Hidden) - { - _logger.LogWindowEvent("Focusing off-screen window", window); - var workspace = WorkspaceService.GetWorkspaceFromChildContainer(window); - _bus.Invoke(new FocusWorkspaceCommand(workspace.Name)); - } + // if (window.DisplayState is DisplayState.Hidden) + // { + // _logger.LogWindowEvent("Focusing off-screen window", window); + // var workspace = WorkspaceService.GetWorkspaceFromChildContainer(window); + // _bus.Invoke(new FocusWorkspaceCommand(workspace.Name)); + // _bus.Emit(new FocusChangedEvent(window)); + // return; + // } _logger.LogWindowEvent("Window focused", window); diff --git a/GlazeWM.Domain/Windows/EventHandlers/WindowHiddenHandler.cs b/GlazeWM.Domain/Windows/EventHandlers/WindowHiddenHandler.cs index 584a459b4..b12cc248f 100644 --- a/GlazeWM.Domain/Windows/EventHandlers/WindowHiddenHandler.cs +++ b/GlazeWM.Domain/Windows/EventHandlers/WindowHiddenHandler.cs @@ -53,8 +53,28 @@ public void Handle(WindowHiddenEvent @event) } // Detach the hidden window from its parent. - if (window.DisplayState is DisplayState.Shown) + if (window.DisplayState is DisplayState.Shown && !WindowService.IsHandleVisible(window.Handle)) _bus.Invoke(new UnmanageWindowCommand(window)); } } } + +// Scenario 1: +// window hiding (due to focus defocus) +// window showing (due to focus refocus) +// window hidden event +// window shown event + +// Scenario 2: +// window hiding (due to focus defocus) +// window hidden event +// window showing (due to focus refocus) +// window shown event + +// Scenario 3: +// window hiding (due to focus defocus) +// window showing (due to focus refocus) +// window hiding (due to focus defocus) +// window hidden event +// window shown event +// window hidden event diff --git a/GlazeWM.Domain/Windows/Window.cs b/GlazeWM.Domain/Windows/Window.cs index d7a170152..526082d88 100644 --- a/GlazeWM.Domain/Windows/Window.cs +++ b/GlazeWM.Domain/Windows/Window.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using GlazeWM.Domain.Common; using GlazeWM.Domain.Common.Enums; using GlazeWM.Domain.Containers; @@ -17,7 +18,17 @@ public abstract class Window : Container /// /// Whether window is shown, hidden, or in an intermediary state. /// - public DisplayState DisplayState { get; set; } = DisplayState.Shown; + private DisplayState _displayState = DisplayState.Shown; + public DisplayState DisplayState + { + get => _displayState; + set + { + var Asdf = Enum.GetName(value.GetType(), value); + Debug.WriteLine($"Display state changed {ProcessName} {Title}: {Asdf}"); + _displayState = value; + } + } /// /// The placement of the window when floating. Initialized with window's placement on launch diff --git a/GlazeWM.Domain/Workspaces/CommandHandlers/MoveWindowToWorkspaceHandler.cs b/GlazeWM.Domain/Workspaces/CommandHandlers/MoveWindowToWorkspaceHandler.cs index 8ff474f89..3919cc9cc 100644 --- a/GlazeWM.Domain/Workspaces/CommandHandlers/MoveWindowToWorkspaceHandler.cs +++ b/GlazeWM.Domain/Workspaces/CommandHandlers/MoveWindowToWorkspaceHandler.cs @@ -54,11 +54,19 @@ public CommandResponse Handle(MoveWindowToWorkspaceCommand command) var focusTarget = WindowService.GetFocusTargetAfterRemoval(windowToMove); + // Since the workspace that gets displayed is the last focused child, focus needs to be + // reassigned to the displayed workspace. + var targetMonitor = targetWorkspace.Parent as Monitor; + var focusResetTarget = targetWorkspace.IsDisplayed ? null : targetMonitor.LastFocusedDescendant; + if (windowToMove is TilingWindow) MoveTilingWindowToWorkspace(windowToMove as TilingWindow, targetWorkspace); else _bus.Invoke(new MoveContainerWithinTreeCommand(windowToMove, targetWorkspace, false)); + if (focusResetTarget is not null) + _bus.Invoke(new SetFocusedDescendantCommand(focusResetTarget)); + // Reassign focus to descendant within the current workspace. Need to call // `SetFocusedDescendantCommand` for when commands like `FocusWorkspaceCommand` are called // immediately afterwards and they should behave as if `focusTarget` is the focused