mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 19:27:56 +01:00
update showing location
Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
namespace QuickAccessHost
|
||||
{
|
||||
void start();
|
||||
void show(const POINT& position);
|
||||
void show();
|
||||
void stop();
|
||||
bool is_running();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user