Skip to content

Commit

Permalink
Try avoid moving windows when removing/adding monitors (#824)
Browse files Browse the repository at this point in the history
When Windows removes/adds monitors, it will helpfully move windows to/from monitors. However, Whim is a window manager and we'd like to control this behavior.

To work around Windows' helpfulness, the `WindowManager` and `ButlerEventHandlers` ignore all Windows events for tracked windows. This has the downside of potentially missing a window closing, but I've judged that it's more important to keep windows in the correct workspaces.

Other changes include:

- Removing an ineffectual lock
- Updating some calls to obsolete methods
- Another attempt at avoiding `AccessViolationException` in the `Bar`
  • Loading branch information
dalyIsaac authored Feb 7, 2024
1 parent 5efdd65 commit 7667f4d
Show file tree
Hide file tree
Showing 21 changed files with 365 additions and 372 deletions.
2 changes: 1 addition & 1 deletion docs/docs/getting-started/comparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Whim is the only window manager which is capable of both dynamic and manual mana

[Repository](https://github.com/fuhsjr00/bug.n) | [Documentation](https://github.com/fuhsjr00/bug.n/wiki)

bug.n is an interesting idea, especiallly for users who already use AutoHotKey. Unfortunately, bug.n is no longer actively developed or maintained.
bug.n is an interesting idea, especially for users who already use AutoHotKey. Unfortunately, bug.n is no longer actively developed or maintained.

## FancyWM

Expand Down
8 changes: 8 additions & 0 deletions docs/docs/getting-started/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,11 @@ Examples of troublesome windows include Firefox and JetBrains Gateway.
Windows can launch windows in different locations. Additionally, interacting with some untracked windows like the Windows Taskbar can break focus tracking in Whim.

To counteract this, the <xref:Whim.IRouterManager> has a <xref:Whim.IRouterManager.RouterOptions> property which can configure how new windows are routed - see the <xref:Whim.RouterOptions> enum.

## Adding/removing monitors

When adding and removing monitors, Windows will very helpfully move windows between monitors. However, this conflicts with Whim. To work around Windows' helpfulness, Whim (in the `WindowManager` and `ButlerEventHandlers` will) ignore [`WinEvents`](../architecture/events.md) for 3 seconds for tracked windows. After the 3 seconds have elapsed, Whim will layout all the active workspaces.

## Window overflows given area

Whim will request windows to have a specific size, but some windows (like Spotify) enforce a minimum size and will ignore Whim's instructions. Whim does not account for this. As a result, these stubborn windows will overflow the expected area. This will also result in the [focus indicator](../plugins/focus-indicator.md) highlighting the expected area, not the window's actual area.
3 changes: 3 additions & 0 deletions src/Whim.Bar.Tests/BarPluginTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Microsoft.UI.Dispatching;
using NSubstitute;
using Whim.TestUtils;
using Xunit;
Expand All @@ -12,6 +13,7 @@ public void MonitorManager_MonitorsChanged_RemovedMonitors(IContext context, IMo
// Given
BarConfig barConfig = new(new List<BarComponent>(), new List<BarComponent>(), new List<BarComponent>());
BarPlugin barPlugin = new(context, barConfig);
NativeManagerUtils.SetupTryEnqueue(context);

// When MonitorManager_MonitorsChanged is called with a removed monitor which is not in the map
barPlugin.PreInitialize();
Expand All @@ -26,5 +28,6 @@ public void MonitorManager_MonitorsChanged_RemovedMonitors(IContext context, IMo

// Then an exception is not thrown.
barPlugin.Dispose();
context.NativeManager.Received(1).TryEnqueue(Arg.Any<DispatcherQueueHandler>());
}
}
9 changes: 1 addition & 8 deletions src/Whim.Bar/BarPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,7 @@ private void MonitorManager_MonitorsChanged(object? sender, MonitorsChangedEvent
foreach (IMonitor monitor in e.RemovedMonitors)
{
_monitorBarMap.TryGetValue(monitor, out BarWindow? value);
try
{
value?.Close();
}
catch (AccessViolationException ex)
{
Logger.Error($"Failed to close bar window for monitor {monitor} due to {ex}");
}
_context.NativeManager.TryEnqueue(() => value?.Close());
_monitorBarMap.Remove(monitor);
}

Expand Down
17 changes: 17 additions & 0 deletions src/Whim.TestUtils/NativeManagerUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Microsoft.UI.Dispatching;
using NSubstitute;

namespace Whim.TestUtils;

public static class NativeManagerUtils
{
public static void SetupTryEnqueue(IContext ctx)
{
ctx.NativeManager.When(cnm => cnm.TryEnqueue(Arg.Any<DispatcherQueueHandler>()))
.Do(callInfo =>
{
DispatcherQueueHandler handler = callInfo.ArgAt<DispatcherQueueHandler>(0);
handler.Invoke();
});
}
}
Loading

0 comments on commit 7667f4d

Please sign in to comment.