update showing location

Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
This commit is contained in:
Shawn Yuan (from Dev Box)
2025-12-04 16:21:55 +08:00
parent 4865b44de1
commit 8f6bd72679
5 changed files with 23 additions and 252 deletions

View File

@@ -17,23 +17,13 @@ extern void receive_json_send_to_main_thread(const std::wstring& msg);
namespace
{
struct PositionPayload
{
LONG x;
LONG y;
LONG sequence;
};
wil::unique_handle quick_access_process;
wil::unique_handle show_event;
wil::unique_handle exit_event;
wil::unique_handle position_mapping;
std::wstring show_event_name;
std::wstring exit_event_name;
std::wstring position_mapping_name;
std::wstring runner_pipe_name;
std::wstring app_pipe_name;
PositionPayload* position_payload = nullptr;
std::unique_ptr<TwoWayPipeMessageIPC> quick_access_ipc;
std::mutex quick_access_mutex;
@@ -62,19 +52,11 @@ namespace
quick_access_ipc.reset();
}
if (position_payload)
{
UnmapViewOfFile(position_payload);
position_payload = nullptr;
}
quick_access_process.reset();
show_event.reset();
exit_event.reset();
position_mapping.reset();
show_event_name.clear();
exit_event_name.clear();
position_mapping_name.clear();
runner_pipe_name.clear();
app_pipe_name.clear();
}
@@ -98,8 +80,6 @@ namespace
command_line += show_event_name;
command_line += L"\" --exit-event=\"";
command_line += exit_event_name;
command_line += L"\" --position-map=\"";
command_line += position_mapping_name;
command_line += L"\"";
if (!runner_pipe_name.empty())
{
@@ -137,7 +117,6 @@ namespace QuickAccessHost
show_event_name = build_event_name(L"_Show");
exit_event_name = build_event_name(L"_Exit");
position_mapping_name = build_event_name(L"_Position");
show_event.reset(CreateEventW(nullptr, FALSE, FALSE, show_event_name.c_str()));
if (!show_event)
@@ -155,27 +134,6 @@ namespace QuickAccessHost
return;
}
position_mapping.reset(CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, sizeof(PositionPayload), position_mapping_name.c_str()));
if (!position_mapping)
{
Logger::error(L"QuickAccessHost: failed to create position mapping. error={}.", GetLastError());
reset_state_locked();
return;
}
auto view = MapViewOfFile(position_mapping.get(), FILE_MAP_ALL_ACCESS, 0, 0, sizeof(PositionPayload));
if (!view)
{
Logger::error(L"QuickAccessHost: failed to map position view. error={}.", GetLastError());
reset_state_locked();
return;
}
position_payload = static_cast<PositionPayload*>(view);
position_payload->x = 0;
position_payload->y = 0;
position_payload->sequence = 0;
runner_pipe_name = L"\\\\.\\pipe\\powertoys_quick_access_runner_";
app_pipe_name = L"\\\\.\\pipe\\powertoys_quick_access_ui_";
UUID temp_uuid;
@@ -258,17 +216,10 @@ namespace QuickAccessHost
CloseHandle(process_info.hThread);
}
void show(const POINT& position)
void show()
{
start();
std::scoped_lock lock(quick_access_mutex);
if (position_payload)
{
InterlockedIncrement(&position_payload->sequence);
InterlockedExchange(&position_payload->x, position.x);
InterlockedExchange(&position_payload->y, position.y);
InterlockedIncrement(&position_payload->sequence);
}
if (show_event)
{

View File

@@ -6,7 +6,7 @@
namespace QuickAccessHost
{
void start();
void show(const POINT& position);
void show();
void stop();
bool is_running();
}

View File

@@ -70,9 +70,9 @@ void change_menu_item_text(const UINT item_id, wchar_t* new_text)
SetMenuItemInfoW(h_menu, item_id, false, &menuitem);
}
void open_quick_access_flyout_window(const POINT flyout_position)
void open_quick_access_flyout_window()
{
QuickAccessHost::show(flyout_position);
QuickAccessHost::show();
}
void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
@@ -114,9 +114,7 @@ void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
}
case ID_QUICK_ACCESS_MENU_COMMAND:
{
POINT mouse_pointer;
GetCursorPos(&mouse_pointer);
open_quick_access_flyout_window(mouse_pointer);
open_quick_access_flyout_window();
break;
}
}
@@ -127,7 +125,7 @@ void click_timer_elapsed()
double_click_timer_running = false;
if (!double_clicked)
{
open_quick_access_flyout_window(tray_icon_click_point);
open_quick_access_flyout_window();
}
}
@@ -219,9 +217,6 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
// ignore event if this is the second click of a double click
if (!double_click_timer_running)
{
// save the cursor position for sending where to show the popup.
GetCursorPos(&tray_icon_click_point);
// start timer for detecting single or double click
double_click_timer_running = true;
double_clicked = false;

View File

@@ -7,13 +7,12 @@ using System.Diagnostics.CodeAnalysis;
namespace Microsoft.PowerToys.QuickAccess;
public sealed record QuickAccessLaunchContext(string? ShowEventName, string? ExitEventName, string? PositionMapName, string? RunnerPipeName, string? AppPipeName)
public sealed record QuickAccessLaunchContext(string? ShowEventName, string? ExitEventName, string? RunnerPipeName, string? AppPipeName)
{
public static QuickAccessLaunchContext Parse(string[] args)
{
string? showEvent = null;
string? exitEvent = null;
string? positionMap = null;
string? runnerPipe = null;
string? appPipe = null;
@@ -27,10 +26,6 @@ public sealed record QuickAccessLaunchContext(string? ShowEventName, string? Exi
{
exitEvent = value;
}
else if (TryReadValue(arg, "--position-map", out value))
{
positionMap = value;
}
else if (TryReadValue(arg, "--runner-pipe", out value))
{
runnerPipe = value;
@@ -41,7 +36,7 @@ public sealed record QuickAccessLaunchContext(string? ShowEventName, string? Exi
}
}
return new QuickAccessLaunchContext(showEvent, exitEvent, positionMap, runnerPipe, appPipe);
return new QuickAccessLaunchContext(showEvent, exitEvent, runnerPipe, appPipe);
}
private static bool TryReadValue(string candidate, string key, [NotNullWhen(true)] out string? value)

View File

@@ -40,9 +40,6 @@ public sealed partial class MainWindow : WindowEx, IDisposable
// Prevent auto-hide until the window actually gained focus once.
private bool _hasSeenInteractiveActivation;
private MemoryMappedFile? _positionMap;
private MemoryMappedViewAccessor? _positionView;
private PointInt32? _lastRequestedPosition;
private bool _isVisible;
private IntPtr _mouseHook;
private LowLevelMouseProc? _mouseHookDelegate;
@@ -140,7 +137,6 @@ public sealed partial class MainWindow : WindowEx, IDisposable
private void InitializeEventListeners()
{
InitializePositionMapping();
if (!string.IsNullOrEmpty(_launchContext.ShowEventName))
{
try
@@ -173,60 +169,26 @@ public sealed partial class MainWindow : WindowEx, IDisposable
if (_hwnd != IntPtr.Zero)
{
UncloakWindow();
var positionApplied = TryReadRequestedPosition(out var requestedPosition);
if (!positionApplied && _lastRequestedPosition.HasValue)
{
requestedPosition = _lastRequestedPosition.Value;
positionApplied = true;
}
if (positionApplied)
{
_lastRequestedPosition = requestedPosition;
}
ShowWindowNative(_hwnd, SwShow);
var flags = SwpNoSize | SwpShowWindow;
var targetX = 0;
var targetY = 0;
if (!positionApplied)
{
flags |= SwpNoMove;
}
else
{
var windowSize = _appWindow?.Size;
var windowWidth = windowSize?.Width ?? DefaultWidth;
var windowHeight = windowSize?.Height ?? DefaultHeight;
targetX = requestedPosition.X - (windowWidth / 2);
targetY = requestedPosition.Y - windowHeight;
var windowSize = _appWindow?.Size;
var windowWidth = windowSize?.Width ?? DefaultWidth;
var windowHeight = windowSize?.Height ?? DefaultHeight;
var monitorHandle = MonitorFromPointNative(new NativePoint { X = requestedPosition.X, Y = requestedPosition.Y }, MonitorDefaulttonearest);
if (monitorHandle != IntPtr.Zero)
GetCursorPos(out var cursorPosition);
var monitorHandle = MonitorFromPointNative(cursorPosition, MonitorDefaulttonearest);
if (monitorHandle != IntPtr.Zero)
{
var monitorInfo = new MonitorInfo { CbSize = Marshal.SizeOf<MonitorInfo>() };
if (GetMonitorInfoNative(monitorHandle, ref monitorInfo))
{
var monitorInfo = new MonitorInfo { CbSize = Marshal.SizeOf<MonitorInfo>() };
if (GetMonitorInfoNative(monitorHandle, ref monitorInfo))
{
var minX = monitorInfo.RcWork.Left;
var maxX = monitorInfo.RcWork.Right - windowWidth;
if (maxX < minX)
{
maxX = minX;
}
targetX = Math.Clamp(targetX, minX, maxX);
var minY = monitorInfo.RcWork.Top;
var maxY = monitorInfo.RcWork.Bottom - windowHeight;
if (maxY < minY)
{
maxY = minY;
}
targetY = Math.Clamp(targetY, minY, maxY);
}
targetX = monitorInfo.RcWork.Right - windowWidth;
targetY = monitorInfo.RcWork.Bottom - windowHeight;
}
}
@@ -373,7 +335,6 @@ public sealed partial class MainWindow : WindowEx, IDisposable
}
RemoveGlobalMouseHook();
DisposePositionResources();
_coordinator.Dispose();
}
@@ -665,141 +626,6 @@ public sealed partial class MainWindow : WindowEx, IDisposable
thread = null;
}
private void InitializePositionMapping()
{
if (string.IsNullOrEmpty(_launchContext.PositionMapName) || _positionMap != null)
{
return;
}
try
{
_positionMap = MemoryMappedFile.OpenExisting(_launchContext.PositionMapName!, MemoryMappedFileRights.Read);
_positionView = _positionMap.CreateViewAccessor(0, sizeof(int) * 3, MemoryMappedFileAccess.Read);
}
catch (FileNotFoundException)
{
}
catch (IOException)
{
}
catch (UnauthorizedAccessException)
{
}
}
private bool TryReadRequestedPosition(out PointInt32 position)
{
position = default;
if (_positionView == null)
{
return false;
}
const int xOffset = 0;
const int yOffset = sizeof(int);
const int sequenceOffset = sizeof(int) * 2;
for (var attempt = 0; attempt < 3; attempt++)
{
int startSequence;
try
{
startSequence = _positionView.ReadInt32(sequenceOffset);
}
catch (ObjectDisposedException)
{
return false;
}
catch (IOException)
{
return false;
}
catch (UnauthorizedAccessException)
{
return false;
}
if ((startSequence & 1) != 0)
{
Thread.Yield();
continue;
}
int x;
int y;
try
{
x = _positionView.ReadInt32(xOffset);
y = _positionView.ReadInt32(yOffset);
}
catch (ObjectDisposedException)
{
return false;
}
catch (IOException)
{
return false;
}
catch (UnauthorizedAccessException)
{
return false;
}
int endSequence;
try
{
endSequence = _positionView.ReadInt32(sequenceOffset);
}
catch (ObjectDisposedException)
{
return false;
}
catch (IOException)
{
return false;
}
catch (UnauthorizedAccessException)
{
return false;
}
if (startSequence == endSequence)
{
position = new PointInt32(x, y);
return true;
}
Thread.Yield();
}
return false;
}
private void DisposePositionResources()
{
try
{
_positionView?.Dispose();
}
catch (ObjectDisposedException)
{
}
_positionView = null;
try
{
_positionMap?.Dispose();
}
catch (ObjectDisposedException)
{
}
_positionMap = null;
_lastRequestedPosition = null;
}
private void CustomizeWindowChrome()
{
if (_hwnd == IntPtr.Zero)
@@ -847,6 +673,10 @@ public sealed partial class MainWindow : WindowEx, IDisposable
private const int WmLbuttondown = 0x0201;
private const int WmRbuttondown = 0x0204;
private const int WmMbuttondown = 0x0207;
[DllImport("user32.dll")]
private static extern bool GetCursorPos(out NativePoint lpPoint);
private const int WmXbuttondown = 0x020B;
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);