Skip to content

Commit

Permalink
Made a bunch more stuff async, which is necessary for the Linux version
Browse files Browse the repository at this point in the history
  • Loading branch information
flyingpie committed Jul 14, 2024
1 parent 7b238d2 commit 4a77d31
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 66 deletions.
4 changes: 2 additions & 2 deletions src/10-Core/Wtq/Services/IWtqProcessService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ public interface IWtqProcessService
/// <summary>
/// Create a new process instance as defined by <see cref="WtqAppOptions"/>'s parameters.
/// </summary>
Task<WtqWindow?> CreateAsync(WtqAppOptions opts);
Task CreateAsync(WtqAppOptions opts);

/// <summary>
/// Looks for a process that matches the specified <paramref name="opts"/>.
/// </summary>
WtqWindow? FindProcess(WtqAppOptions opts);
Task<WtqWindow?> FindProcessAsync(WtqAppOptions opts);

/// <summary>
/// Returns the process that currently has UI focus.
Expand Down
6 changes: 3 additions & 3 deletions src/10-Core/Wtq/Services/IWtqScreenInfoProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ namespace Wtq.Services;

public interface IWtqScreenInfoProvider
{
WtqRect GetPrimaryScreenRect();
Task<WtqRect> GetPrimaryScreenRectAsync();

WtqRect[] GetScreenRects();
Task<WtqRect[]> GetScreenRectsAsync();

WtqRect GetScreenWithCursor();
Task<WtqRect> GetScreenWithCursorAsync();
}
20 changes: 10 additions & 10 deletions src/10-Core/Wtq/Services/WtqAppToggleService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public async Task ToggleOffAsync(WtqApp app, ToggleModifiers mods)

_log.LogInformation("ToggleOff from '{From}' to '{To}'", from, to);

await _tween.AnimateAsync(from, to, durationMs, AnimationType.EaseInQuart, app.MoveWindow).ConfigureAwait(false);
await _tween.AnimateAsync(from, to, durationMs, AnimationType.EaseInQuart, app.MoveWindowAsync).NoCtx();
}

/// <inheritdoc/>
Expand All @@ -34,14 +34,14 @@ public async Task ToggleOnAsync(WtqApp app, ToggleModifiers mods)
Guard.Against.Null(app);

// Make sure the app has focus.
app.BringToForeground();
await app.BringToForegroundAsync().NoCtx();

var durationMs = GetDurationMs(app, mods);
var screen = GetToggleOnToScreenRect(app);
var screen = await GetToggleOnToScreenRectAsync(app).NoCtx();
var to = GetToggleOnToWindowRect(app, screen);
var from = GetToggleOnFromWindowRect(to);

await _tween.AnimateAsync(from, to, durationMs, AnimationType.EaseOutQuart, app.MoveWindow).ConfigureAwait(false);
await _tween.AnimateAsync(from, to, durationMs, AnimationType.EaseOutQuart, app.MoveWindowAsync).NoCtx();

_log.LogInformation("ToggleOn from '{From}' to '{To}'", from, to);
}
Expand Down Expand Up @@ -94,7 +94,7 @@ private WtqRect GetToggleOnFromWindowRect(WtqRect to)
/// Returns a rectangle representing the screen we want to toggle the terminal onto.
/// </summary>
/// <param name="app">The app for which we're figuring out the screen bounds.</param>
private WtqRect GetToggleOnToScreenRect(WtqApp app)
private async Task<WtqRect> GetToggleOnToScreenRectAsync(WtqApp app)
{
Guard.Against.Null(app);

Expand All @@ -105,7 +105,7 @@ private WtqRect GetToggleOnToScreenRect(WtqApp app)
{
case PreferMonitor.AtIndex:
{
var screens = _scrInfoProvider.GetScreenRects();
var screens = await _scrInfoProvider.GetScreenRectsAsync().NoCtx();

if (screens.Length > monInd)
{
Expand All @@ -118,14 +118,14 @@ private WtqRect GetToggleOnToScreenRect(WtqApp app)
monInd,
screens.Length);

return _scrInfoProvider.GetPrimaryScreenRect();
return await _scrInfoProvider.GetPrimaryScreenRectAsync().NoCtx();
}

case PreferMonitor.Primary:
return _scrInfoProvider.GetPrimaryScreenRect();
return await _scrInfoProvider.GetPrimaryScreenRectAsync().NoCtx();

case PreferMonitor.WithCursor:
return _scrInfoProvider.GetScreenWithCursor();
return await _scrInfoProvider.GetScreenWithCursorAsync().NoCtx();

default:
{
Expand All @@ -134,7 +134,7 @@ private WtqRect GetToggleOnToScreenRect(WtqApp app)
prefMon,
nameof(app.Options.PreferMonitor));

return _scrInfoProvider.GetPrimaryScreenRect();
return await _scrInfoProvider.GetPrimaryScreenRectAsync().NoCtx();
}
}
}
Expand Down
42 changes: 23 additions & 19 deletions src/10-Core/Wtq/Services/WtqProcessFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
public sealed class WtqProcessFactory : IWtqProcessFactory
{
private readonly IOptions<WtqOptions> _opts;
private readonly IRetry _retry;
private readonly IWtqProcessService _procService;

public WtqProcessFactory(
IOptions<WtqOptions> opts,
IRetry retry,
IWtqProcessService procService)
{
_opts = Guard.Against.Null(opts);
_retry = Guard.Against.Null(retry);
_procService = Guard.Against.Null(procService);
}

Expand All @@ -23,34 +26,35 @@ public WtqProcessFactory(
switch (opts.AttachMode ?? _opts.Value.AttachMode)
{
case AttachMode.Manual:
{
return null;
}
{
return null;
}

case AttachMode.Find:
{
return _procService.FindProcess(opts);
}
{
return await _procService.FindProcessAsync(opts).NoCtx();
}

default:
case AttachMode.FindOrStart:
{
for (var i = 0; i < 5; i++)
{
var proc = _procService.FindProcess(opts);

if (proc != null)
{
return await _retry
.ExecuteAsync(
async () =>
{
return proc;
}
var proc = await _procService.FindProcessAsync(opts).NoCtx();
await _procService.CreateAsync(opts).ConfigureAwait(false);
if (proc != null)
{
return proc;
}
await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
}
await _procService.CreateAsync(opts).NoCtx();
throw new WtqException($"Failed to find or start window for app '{opts}'.");
}
throw new WtqException($"Failed to find or start window for app '{opts}'.");
})
.NoCtx();
}
}
}
}
25 changes: 12 additions & 13 deletions src/10-Core/Wtq/WtqApp.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Wtq.Data;
using Wtq.Services;
using Wtq.Services.Apps;

namespace Wtq;

Expand Down Expand Up @@ -61,7 +60,7 @@ public async Task AttachAsync(WtqWindow process)
// TODO: Configurable.
if (_opts.CurrentValue.GetTaskbarIconVisibilityForApp(Options) == TaskBarIconVisibility.AlwaysHidden)
{
process.SetTaskbarIconVisible(false);
await process.SetTaskbarIconVisibleAsync(false).NoCtx();
}

await CloseAsync(ToggleModifiers.Instant).ConfigureAwait(false);
Expand All @@ -72,14 +71,14 @@ public async Task AttachAsync(WtqWindow process)
/// <summary>
/// Puts the window associated with the process on top of everything and gives it focus.
/// </summary>
public void BringToForeground()
public async Task BringToForegroundAsync()
{
if (Process == null)
{
throw new InvalidOperationException($"App '{this}' does not have a process attached.");
}

Process.BringToForeground();
await Process.BringToForegroundAsync().NoCtx();
}

public async Task CloseAsync(ToggleModifiers mods = ToggleModifiers.None)
Expand All @@ -105,13 +104,13 @@ public async ValueTask DisposeAsync()
_log.LogInformation("Restoring process '{Process}' to its original bounds of '{Bounds}'", ProcessDescription, bounds);

// Toggle app onto the screen again.
await OpenAsync(ToggleModifiers.Instant).ConfigureAwait(false);
await OpenAsync(ToggleModifiers.Instant).NoCtx();

// Restore "always on top" state.
Process.SetAlwaysOnTop(false);
await Process.SetAlwaysOnTopAsync(false).NoCtx();

// Restore taskbar icon visibility.
Process.SetTaskbarIconVisible(true);
await Process.SetTaskbarIconVisibleAsync(true).NoCtx();
}
}

Expand All @@ -126,14 +125,14 @@ public WtqRect GetWindowRect()
return Process.WindowRect;
}

public void MoveWindow(WtqRect rect)
public async Task MoveWindowAsync(WtqRect rect)
{
if (Process == null)
{
throw new InvalidOperationException($"App '{this}' does not have a process attached.");
}

Process.MoveTo(rect: rect);
await Process.MoveToAsync(rect: rect).NoCtx();
}

public async Task<bool> OpenAsync(ToggleModifiers mods = ToggleModifiers.None)
Expand All @@ -143,7 +142,7 @@ public async Task<bool> OpenAsync(ToggleModifiers mods = ToggleModifiers.None)
{
_log.LogInformation("Opening app '{App}'", this);

await _toggler.ToggleOnAsync(this, mods).ConfigureAwait(false);
await _toggler.ToggleOnAsync(this, mods).NoCtx();

return true;
}
Expand Down Expand Up @@ -191,7 +190,7 @@ public async Task UpdateAsync()

if (Process == null)
{
var process = await _procFactory.GetProcessAsync(Options).ConfigureAwait(false);
var process = await _procFactory.GetProcessAsync(Options).NoCtx();

if (process == null)
{
Expand All @@ -205,10 +204,10 @@ public async Task UpdateAsync()
if (Process != null && IsActive)
{
// Always on top.
Process.SetAlwaysOnTop(_opts.CurrentValue.GetAlwaysOnTopForApp(Options));
await Process.SetAlwaysOnTopAsync(_opts.CurrentValue.GetAlwaysOnTopForApp(Options)).NoCtx();

// Opacity.
Process.SetTransparency(_opts.CurrentValue.GetOpacityForApp(Options));
await Process.SetTransparencyAsync(_opts.CurrentValue.GetOpacityForApp(Options)).NoCtx();
}
}
}
12 changes: 7 additions & 5 deletions src/10-Core/Wtq/WtqWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,19 @@ public override int GetHashCode()
return Id;
}

public abstract void BringToForeground();
public abstract Task BringToForegroundAsync();

public abstract bool Matches(WtqAppOptions opts);

public abstract void MoveTo(WtqRect rect, bool repaint = true);
public abstract Task MoveToAsync(WtqRect rect, bool repaint = true);

public abstract void SetAlwaysOnTop(bool isAlwaysOnTop);
public abstract Task SetAlwaysOnTopAsync(bool isAlwaysOnTop);

public abstract void SetTaskbarIconVisible(bool isVisible);
public abstract Task SetTaskbarIconVisibleAsync(bool isVisible);

public abstract void SetTransparency(int transparency);
public abstract Task SetTransparencyAsync(int transparency);

public abstract Task SetVisibleAsync(bool isVisible);

public override string ToString() => $"[{Id}] {Name}";
}
27 changes: 21 additions & 6 deletions src/20-Services/Wtq.Services.Win32/Win32WtqProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ public override WtqRect WindowRect
}
}

public override void BringToForeground()
public override Task BringToForegroundAsync()
{
User32.SetForegroundWindow(_process.MainWindowHandle);
User32.ForcePaint(_process.MainWindowHandle);

return Task.CompletedTask;
}

public override bool Matches(WtqAppOptions opts)
Expand All @@ -55,7 +57,7 @@ public override bool Matches(WtqAppOptions opts)
return expectedProcName.Equals(_process.ProcessName, StringComparison.OrdinalIgnoreCase);
}

public override void MoveTo(WtqRect rect, bool repaint = true)
public override Task MoveToAsync(WtqRect rect, bool repaint = true)
{
User32.MoveWindow(
hWnd: _process.MainWindowHandle,
Expand All @@ -64,9 +66,11 @@ public override void MoveTo(WtqRect rect, bool repaint = true)
nWidth: (int)rect.Width,
nHeight: (int)rect.Height,
bRepaint: repaint);

return Task.CompletedTask;
}

public override void SetAlwaysOnTop(bool isAlwaysOnTop)
public override Task SetAlwaysOnTopAsync(bool isAlwaysOnTop)
{
if (_process.MainWindowHandle == IntPtr.Zero)
{
Expand All @@ -86,9 +90,11 @@ public override void SetAlwaysOnTop(bool isAlwaysOnTop)
{
throw new WtqException("Could not set window top most");
}

return Task.CompletedTask;
}

public override void SetTaskbarIconVisible(bool isVisible)
public override Task SetTaskbarIconVisibleAsync(bool isVisible)
{
// Get handle to the main window
var handle = _process.MainWindowHandle;
Expand All @@ -108,13 +114,15 @@ public override void SetTaskbarIconVisible(bool isVisible)
// Hide
User32.SetWindowLong(handle, User32.GWLEXSTYLE, (props | User32.WSEXTOOLWINDOW) & ~User32.WSEXAPPWINDOW);
}

return Task.CompletedTask;
}

public override void SetTransparency(int transparency)
public override Task SetTransparencyAsync(int transparency)
{
if (transparency >= 100)
{
return;
return Task.CompletedTask;
}

if (_process.MainWindowHandle == IntPtr.Zero)
Expand All @@ -139,5 +147,12 @@ public override void SetTransparency(int transparency)
{
throw new WtqException("Could not set window opacity");
}

return Task.CompletedTask;
}

public override Task SetVisibleAsync(bool isVisible)
{
return Task.CompletedTask;
}
}
Loading

0 comments on commit 4a77d31

Please sign in to comment.