mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 11:17:53 +01:00
[Workspaces] fix hotkey behavior (#34497)
* [Workspaces] re-implementing hotkey handling * [Workspaces] fix interop reference * Reimplement message sending * cleanup * Do not recreate event * bring back minimized logic --------- Co-authored-by: Stefan Markovic <stefan@janeasystems.com>
This commit is contained in:
@@ -151,4 +151,8 @@ namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
return CommonSharedConstants::WORKSPACES_LAUNCH_EDITOR_EVENT;
|
||||
}
|
||||
hstring Constants::WorkspacesHotkeyEvent()
|
||||
{
|
||||
return CommonSharedConstants::WORKSPACES_HOTKEY_EVENT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace winrt::PowerToys::Interop::implementation
|
||||
static hstring ShowEnvironmentVariablesSharedEvent();
|
||||
static hstring ShowEnvironmentVariablesAdminSharedEvent();
|
||||
static hstring WorkspacesLaunchEditorEvent();
|
||||
static hstring WorkspacesHotkeyEvent();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace PowerToys
|
||||
static String ShowEnvironmentVariablesSharedEvent();
|
||||
static String ShowEnvironmentVariablesAdminSharedEvent();
|
||||
static String WorkspacesLaunchEditorEvent();
|
||||
static String WorkspacesHotkeyEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,9 @@ namespace CommonSharedConstants
|
||||
|
||||
const wchar_t FANCY_ZONES_EDITOR_TOGGLE_EVENT[] = L"Local\\FancyZones-ToggleEditorEvent-1e174338-06a3-472b-874d-073b21c62f14";
|
||||
|
||||
// Path to the event used by Workspaces
|
||||
const wchar_t WORKSPACES_LAUNCH_EDITOR_EVENT[] = L"Local\\Workspaces-LaunchEditorEvent-a55ff427-cf62-4994-a2cd-9f72139296bf";
|
||||
const wchar_t WORKSPACES_HOTKEY_EVENT[] = L"Local\\PowerToys-Workspaces-HotkeyEvent-2625C3C8-BAC9-4DB3-BCD6-3B4391A26FD0";
|
||||
|
||||
const wchar_t SHOW_HOSTS_EVENT[] = L"Local\\Hosts-ShowHostsEvent-5a0c0aae-5ff5-40f5-95c2-20e37ed671f0";
|
||||
|
||||
@@ -100,8 +102,6 @@ namespace CommonSharedConstants
|
||||
const wchar_t SHOW_ENVIRONMENT_VARIABLES_EVENT[] = L"Local\\PowerToysEnvironmentVariables-ShowEnvironmentVariablesEvent-1021f616-e951-4d64-b231-a8f972159978";
|
||||
const wchar_t SHOW_ENVIRONMENT_VARIABLES_ADMIN_EVENT[] = L"Local\\PowerToysEnvironmentVariables-EnvironmentVariablesAdminEvent-8c95d2ad-047c-49a2-9e8b-b4656326cfb2";
|
||||
|
||||
const wchar_t WORKSPACES_EXIT_EVENT[] = L"Local\\PowerToys-Workspaces-ExitEvent-29a1566f-f4f8-4d56-9435-d2a437f727c6";
|
||||
|
||||
// Max DWORD for key code to disable keys.
|
||||
const DWORD VK_DISABLED = 0x100;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using ManagedCommon;
|
||||
@@ -14,10 +15,12 @@ namespace WorkspacesEditor
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
public partial class MainWindow : Window, IDisposable
|
||||
{
|
||||
public MainViewModel MainViewModel { get; set; }
|
||||
|
||||
private CancellationTokenSource cancellationToken = new CancellationTokenSource();
|
||||
|
||||
private static MainPage _mainPage;
|
||||
|
||||
public MainWindow(MainViewModel mainViewModel)
|
||||
@@ -41,10 +44,36 @@ namespace WorkspacesEditor
|
||||
|
||||
MaxWidth = SystemParameters.PrimaryScreenWidth;
|
||||
MaxHeight = SystemParameters.PrimaryScreenHeight;
|
||||
|
||||
Common.UI.NativeEventWaiter.WaitForEventLoop(
|
||||
PowerToys.Interop.Constants.WorkspacesHotkeyEvent(),
|
||||
() =>
|
||||
{
|
||||
if (ApplicationIsInFocus())
|
||||
{
|
||||
Environment.Exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (WindowState == WindowState.Minimized)
|
||||
{
|
||||
WindowState = WindowState.Normal;
|
||||
}
|
||||
|
||||
// Get the window handle of the Workspaces Editor window
|
||||
IntPtr handle = new WindowInteropHelper(this).Handle;
|
||||
WindowHelpers.BringToForeground(handle);
|
||||
|
||||
InvalidateVisual();
|
||||
}
|
||||
},
|
||||
Application.Current.Dispatcher,
|
||||
cancellationToken.Token);
|
||||
}
|
||||
|
||||
private void OnClosing(object sender, EventArgs e)
|
||||
{
|
||||
cancellationToken.Dispose();
|
||||
App.Current.Shutdown();
|
||||
}
|
||||
|
||||
@@ -67,5 +96,25 @@ namespace WorkspacesEditor
|
||||
{
|
||||
ContentFrame.GoBack();
|
||||
}
|
||||
|
||||
public static bool ApplicationIsInFocus()
|
||||
{
|
||||
var activatedHandle = NativeMethods.GetForegroundWindow();
|
||||
if (activatedHandle == IntPtr.Zero)
|
||||
{
|
||||
return false; // No window is currently activated
|
||||
}
|
||||
|
||||
var procId = Environment.ProcessId;
|
||||
int activeProcId;
|
||||
_ = NativeMethods.GetWindowThreadProcessId(activatedHandle, out activeProcId);
|
||||
|
||||
return activeProcId == procId;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace WorkspacesEditor.Utils
|
||||
public static extern IntPtr GetForegroundWindow();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr processId);
|
||||
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int processId);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint GetCurrentThreadId();
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
{
|
||||
if (is_process_running())
|
||||
{
|
||||
bring_process_to_front();
|
||||
sendHotkeyEvent();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -164,6 +164,12 @@ public:
|
||||
m_toggleEditorEvent = nullptr;
|
||||
}
|
||||
|
||||
if (m_hotkeyEvent)
|
||||
{
|
||||
CloseHandle(m_hotkeyEvent);
|
||||
m_hotkeyEvent = nullptr;
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
@@ -178,6 +184,12 @@ public:
|
||||
LoggerHelpers::init_logger(app_key, L"ModuleInterface", "Workspaces");
|
||||
init_settings();
|
||||
|
||||
m_hotkeyEvent = CreateEventW(nullptr, false, false, CommonSharedConstants::WORKSPACES_HOTKEY_EVENT);
|
||||
if (!m_hotkeyEvent)
|
||||
{
|
||||
Logger::warn(L"Failed to create hotkey event. {}", get_last_error_or_default(GetLastError()));
|
||||
}
|
||||
|
||||
m_toggleEditorEvent = CreateDefaultEvent(CommonSharedConstants::WORKSPACES_LAUNCH_EDITOR_EVENT);
|
||||
if (!m_toggleEditorEvent)
|
||||
{
|
||||
@@ -210,23 +222,12 @@ private:
|
||||
executable_args.append(std::to_wstring(powertoys_pid));
|
||||
}
|
||||
|
||||
void SendCloseEvent()
|
||||
void sendHotkeyEvent()
|
||||
{
|
||||
auto exitEvent = CreateEventW(nullptr, false, false, CommonSharedConstants::WORKSPACES_EXIT_EVENT);
|
||||
if (!exitEvent)
|
||||
Logger::trace(L"Signaled hotkey event");
|
||||
if (!SetEvent(m_hotkeyEvent))
|
||||
{
|
||||
Logger::warn(L"Failed to create exitEvent. {}", get_last_error_or_default(GetLastError()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::trace(L"Signaled exitEvent");
|
||||
if (!SetEvent(exitEvent))
|
||||
{
|
||||
Logger::warn(L"Failed to signal exitEvent. {}", get_last_error_or_default(GetLastError()));
|
||||
}
|
||||
|
||||
ResetEvent(exitEvent);
|
||||
CloseHandle(exitEvent);
|
||||
Logger::warn(L"Failed to signal hotkey event. {}", get_last_error_or_default(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,10 +245,14 @@ private:
|
||||
ResetEvent(m_toggleEditorEvent);
|
||||
}
|
||||
|
||||
if (m_hotkeyEvent)
|
||||
{
|
||||
ResetEvent(m_hotkeyEvent);
|
||||
}
|
||||
|
||||
if (m_hProcess)
|
||||
{
|
||||
TerminateProcess(m_hProcess, 0);
|
||||
SendCloseEvent();
|
||||
m_hProcess = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -330,23 +335,6 @@ private:
|
||||
m_hProcess = sei.hProcess;
|
||||
}
|
||||
|
||||
void bring_process_to_front()
|
||||
{
|
||||
auto enum_windows = [](HWND hwnd, LPARAM param) -> BOOL {
|
||||
HANDLE process_handle = reinterpret_cast<HANDLE>(param);
|
||||
DWORD window_process_id = 0;
|
||||
|
||||
GetWindowThreadProcessId(hwnd, &window_process_id);
|
||||
if (GetProcessId(process_handle) == window_process_id)
|
||||
{
|
||||
SetForegroundWindow(hwnd);
|
||||
}
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
EnumWindows(enum_windows, (LPARAM)m_hProcess);
|
||||
}
|
||||
|
||||
bool is_process_running() const
|
||||
{
|
||||
return WaitForSingleObject(m_hProcess, 0) == WAIT_TIMEOUT;
|
||||
@@ -362,6 +350,9 @@ private:
|
||||
// Handle to event used to invoke Workspaces Editor
|
||||
HANDLE m_toggleEditorEvent;
|
||||
|
||||
// Handle to event used when hotkey is invoked
|
||||
HANDLE m_hotkeyEvent;
|
||||
|
||||
// Hotkey to invoke the module
|
||||
HotkeyEx m_hotkey{
|
||||
.modifiersMask = MOD_CONTROL | MOD_WIN,
|
||||
|
||||
Reference in New Issue
Block a user