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

Allow widgets to take foreground rights on user interaction #3117

Merged
merged 3 commits into from
Jun 4, 2024
Merged
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 @@ -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)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: nativemethods.txt

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. But checking this in now for Canary this week.

private static extern void CoAllowSetForegroundWindow(IntPtr pUnk, IntPtr lpvReserved);

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