Skip to content

Commit

Permalink
Allow widgets to take foreground rights on user interaction (#3117)
Browse files Browse the repository at this point in the history
* get unsafe widget

* Move foreground call to inside NotifyActionInvokedAsync

* log any error
  • Loading branch information
krschau authored Jun 4, 2024
1 parent 6a16543 commit 5388785
Showing 1 changed file with 28 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using DevHome.Common.Extensions;
Expand Down Expand Up @@ -186,6 +187,17 @@ public async Task NotifyActionInvokedAsync(string verb, string data)
try
{
await LazilyLoadOopWidget();
try
{
CoAllowSetForegroundWindow(_oopWidget);
Log.Information("CoAllowSetForegroundWindow result: {GetLastError}", Marshal.GetLastWin32Error().ToString(CultureInfo.CurrentCulture));
}
catch (Exception ex)
{
// If CoAllowSetForegroundWindow fails, we should still continue with the call to NotifyActionInvokedAsync.
_log.Warning(ex, $"Call to CoAllowSetForegroundWindow failed");
}

await Task.Run(async () => await _oopWidget.NotifyActionInvokedAsync(verb, data));
return;
}
Expand Down Expand Up @@ -359,4 +371,20 @@ public static async Task<string> GetIdFromUnsafeWidgetAsync(Widget widget)
return string.Empty;
});
}

public Widget GetUnsafeWidgetObject()
{
return _oopWidget;
}

// CoAllowSetForegroundWindow must be called on a raw COM interface, not a .NET CCW, in order to work correctly, since
// the underlying functionality is implemented by COM runtime and the object itself. CoAllowSetForegroundWindow wrapper
// below takes a WinRT object and extracts the raw COM interface pointer from it before calling native CoAllowSetForegroundWindow.
[DllImport("ole32.dll", ExactSpelling = true, PreserveSig = false, SetLastError = true)]
private static extern void CoAllowSetForegroundWindow(IntPtr pUnk, IntPtr lpvReserved);

private void CoAllowSetForegroundWindow(Widget widget)
{
CoAllowSetForegroundWindow(Marshal.GetIUnknownForObject(widget), IntPtr.Zero);
}
}

0 comments on commit 5388785

Please sign in to comment.