Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: maximized windows stay maximized #421

Merged
merged 6 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public CommandResponse Handle(RedrawContainersCommand command)
var windowsToRestore = windowsToRedraw
.Where(
(window) =>
window is not MinimizedWindow &&
window.HasWindowStyle(WindowStyles.Maximize | WindowStyles.Minimize)
(window is not MinimizedWindow && window.HasWindowStyle(WindowStyles.Minimize)) ||
(window is not MaximizedWindow && window.HasWindowStyle(WindowStyles.Maximize))
)
.ToList();

Expand Down Expand Up @@ -85,6 +85,9 @@ private void SetWindowPosition(Window window)
else
defaultFlags |= SetWindowPosFlags.HideWindow;

if (window is MaximizedWindow)
defaultFlags |= SetWindowPosFlags.NoSize;

// Transition display state depending on whether window will be shown/hidden.
window.DisplayState = window.DisplayState switch
{
Expand Down
111 changes: 110 additions & 1 deletion GlazeWM.Domain/Windows/EventHandlers/WindowLocationChangedHandler.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,139 @@
using System;
using System.Linq;
using GlazeWM.Domain.Containers;
using GlazeWM.Domain.Containers.Commands;
using GlazeWM.Domain.Monitors.Commands;
using GlazeWM.Domain.Workspaces;
using GlazeWM.Infrastructure.Bussing;
using GlazeWM.Infrastructure.Common.Events;
using static GlazeWM.Infrastructure.WindowsApi.WindowsApiService;

namespace GlazeWM.Domain.Windows.EventHandlers
{
internal sealed class WindowLocationChangedHandler : IEventHandler<WindowLocationChangedEvent>
{
private readonly Bus _bus;
private readonly ContainerService _containerService;
private readonly WindowService _windowService;

public WindowLocationChangedHandler(Bus bus, WindowService windowService)
public WindowLocationChangedHandler(Bus bus,
WindowService windowService,
ContainerService containerService)
{
_bus = bus;
_containerService = containerService;
_windowService = windowService;
}

public void Handle(WindowLocationChangedEvent @event)
{
var windowHandle = @event.WindowHandle;

HandleMaximizedWindow(windowHandle);

if (!_windowService.AppBarHandles.Contains(windowHandle))
return;

_bus.Invoke(new RefreshMonitorStateCommand());
_bus.Invoke(new RedrawContainersCommand());
}

private void HandleMaximizedWindow(IntPtr windowHandle)
{
var window = _windowService.GetWindowByHandle(windowHandle);
if (window is null)
return;

var windowPlacement = WindowService.GetPlacementOfHandle(windowHandle);
var isMaximized = windowPlacement.ShowCommand == ShowWindowFlags.Maximize;

// Window is being maximized.
if (isMaximized && window is not MaximizedWindow)
{
var previousState = WindowService.GetWindowType(window);
var maximizedWindow = new MaximizedWindow(
window.Handle,
window.FloatingPlacement,
window.BorderDelta,
previousState
)
{
Id = window.Id
};

if (!window.HasSiblings() && window.Parent is not Workspace)
_bus.Invoke(new FlattenSplitContainerCommand(window.Parent as SplitContainer));

_bus.Invoke(new ReplaceContainerCommand(maximizedWindow, window.Parent, window.Index));

_containerService.ContainersToRedraw.Concat(window.Siblings);
_bus.Invoke(new RedrawContainersCommand());
}

// Maximized window is being restored.
if (!isMaximized && window is MaximizedWindow)
{
var restoredWindow = CreateWindowFromPreviousState(window as MaximizedWindow);
_bus.Invoke(new ReplaceContainerCommand(restoredWindow, window.Parent, window.Index));

// Non-tiling window expect to be direct children of workspace.
if (restoredWindow is not TilingWindow)
{
var workspace = WorkspaceService.GetWorkspaceFromChildContainer(restoredWindow);
_bus.Invoke(new MoveContainerWithinTreeCommand(restoredWindow, workspace, false));
}
else
{
// TODO: Temporary hack to resize restored tiling window.
_bus.Invoke(
new MoveContainerWithinTreeCommand(
restoredWindow,
restoredWindow.Parent,
restoredWindow.Index,
true
)
);
}

_containerService.ContainersToRedraw.Add(restoredWindow);
_bus.Invoke(new RedrawContainersCommand());
}
}

// TODO: Share logic with `WindowMinimizedHandler`.
private static Window CreateWindowFromPreviousState(MaximizedWindow window)
{
Window restoredWindow = window.PreviousState switch
{
WindowType.Floating => new FloatingWindow(
window.Handle,
window.FloatingPlacement,
window.BorderDelta
),
WindowType.Fullscreen => new FullscreenWindow(
window.Handle,
window.FloatingPlacement,
window.BorderDelta
),
// Set `SizePercentage` to 0 to correctly resize the container when moved within tree.
WindowType.Tiling => new TilingWindow(
window.Handle,
window.FloatingPlacement,
window.BorderDelta,
0
),
WindowType.Minimized => new MinimizedWindow(
window.Handle,
window.FloatingPlacement,
window.BorderDelta,
WindowType.Tiling
),
WindowType.Maximized => throw new ArgumentException(null, nameof(window)),
_ => throw new ArgumentException(null, nameof(window)),
};

restoredWindow.Id = window.Id;
return restoredWindow;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ private static Window CreateWindowFromPreviousState(MinimizedWindow window)
WindowType.Maximized => new MaximizedWindow(
window.Handle,
window.FloatingPlacement,
window.BorderDelta
window.BorderDelta,
WindowType.Tiling
),
WindowType.Fullscreen => new FullscreenWindow(
window.Handle,
Expand Down
6 changes: 5 additions & 1 deletion GlazeWM.Domain/Windows/MaximizedWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ namespace GlazeWM.Domain.Windows
{
public sealed class MaximizedWindow : Window
{
public WindowType PreviousState;

public MaximizedWindow(
IntPtr handle,
Rect floatingPlacement,
RectDelta borderDelta
RectDelta borderDelta,
WindowType previousState
) : base(handle, floatingPlacement, borderDelta)
{
PreviousState = previousState;
}
}
}
1 change: 1 addition & 0 deletions GlazeWM.Domain/Windows/WindowService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ public static WindowType GetWindowType(Window window)
{
TilingWindow => WindowType.Tiling,
FloatingWindow => WindowType.Floating,
MinimizedWindow => WindowType.Minimized,
MaximizedWindow => WindowType.Maximized,
FullscreenWindow => WindowType.Fullscreen,
_ => throw new ArgumentException(null, nameof(window)),
Expand Down