mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-01-18 06:29:44 +08:00
Customize system menu items through dedicated API (#677)
Document new interface changes.
This commit is contained in:
parent
9f78af29bf
commit
be86cd4028
@ -23,6 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "interface", "interface", "{
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
src\modules\interface\lowlevel_keyboard_event_data.h = src\modules\interface\lowlevel_keyboard_event_data.h
|
||||
src\modules\interface\powertoy_module_interface.h = src\modules\interface\powertoy_module_interface.h
|
||||
src\modules\interface\powertoy_system_menu.h = src\modules\interface\powertoy_system_menu.h
|
||||
src\modules\interface\win_hook_event_data.h = src\modules\interface\win_hook_event_data.h
|
||||
EndProjectSection
|
||||
EndProject
|
||||
|
@ -214,6 +214,9 @@ public:
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override { }
|
||||
virtual void signal_system_menu_action(const wchar_t* name) override { }
|
||||
};
|
||||
|
||||
// Load the settings file.
|
||||
|
@ -182,6 +182,9 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override { }
|
||||
virtual void signal_system_menu_action(const wchar_t* name) override { }
|
||||
|
||||
// Destroy the powertoy and free memory
|
||||
virtual void destroy() override
|
||||
{
|
||||
|
@ -19,6 +19,8 @@ public:
|
||||
virtual void disable() = 0;
|
||||
virtual bool is_enabled() = 0;
|
||||
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) = 0;
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) = 0;
|
||||
virtual void signal_system_menu_action(const wchar_t* name) = 0;
|
||||
virtual void destroy() = 0;
|
||||
};
|
||||
|
||||
@ -43,6 +45,8 @@ and destroy():
|
||||
- [`set_config()`](#set_config) to set settings after they have been edited in the Settings editor,
|
||||
- [`call_custom_action()`](#call_custom_action) when the user selects a custom action in the Settings editor,
|
||||
- [`signal_event()`](#signal_event) to send an event the PowerToy registered to.
|
||||
- [`register_system_menu_helper()`](#register_system_menu_helper) to pass object, responsible for handling customized system menus, to module.
|
||||
- [`signal_system_menu_action()`](#signal_system_menu_action) to send an event when action is taken on system menu item.
|
||||
|
||||
When terminating, the runner will:
|
||||
- call [`disable()`](#disable),
|
||||
@ -313,6 +317,25 @@ Sample code from [`the example PowerToy`](/src/modules/example_powertoy/dllmain.
|
||||
}
|
||||
```
|
||||
|
||||
### register_system_menu_helper
|
||||
|
||||
```cpp
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) = 0;
|
||||
```
|
||||
|
||||
Register helper class to handle all system menu items related actions. Creation, deletion
|
||||
and all other actions taken on system menu item will be handled by provided class.
|
||||
Module will be informed when action is taken on any item created on request of the module.
|
||||
|
||||
### signal_system_menu_action
|
||||
|
||||
```cpp
|
||||
virtual void signal_system_menu_action(const wchar_t* name) = 0;
|
||||
```
|
||||
|
||||
Runner invokes this API when action is taken on item created on request from the module.
|
||||
Item name is passed as an argument, so that module can distinguish between different menu items.
|
||||
|
||||
#### destroy
|
||||
|
||||
```cpp
|
||||
@ -328,11 +351,59 @@ Sample code from [`the example PowerToy`](/src/modules/example_powertoy/dllmain.
|
||||
}
|
||||
```
|
||||
|
||||
### Powertoys system menu helper interface
|
||||
|
||||
Interface for helper class responsible for handling all system menu related actions.
|
||||
```cpp
|
||||
class PowertoySystemMenuIface {
|
||||
public:
|
||||
struct ItemInfo {
|
||||
std::wstring name{};
|
||||
bool enable{ false };
|
||||
bool checkBox{ false };
|
||||
};
|
||||
virtual void SetConfiguration(PowertoyModuleIface* module, const std::vector<ItemInfo>& config) = 0;
|
||||
virtual void ProcessSelectedItem(PowertoyModuleIface* module, HWND window, const wchar_t* itemName) = 0;
|
||||
};
|
||||
```
|
||||
|
||||
### ItemInfo
|
||||
|
||||
```cpp
|
||||
struct ItemInfo {
|
||||
std::wstring name{};
|
||||
bool enable{ false };
|
||||
bool checkBox{ false };
|
||||
};
|
||||
```
|
||||
|
||||
Structure containing all relevant information for system menu item: name (and hotkey if available), item
|
||||
status at creation (enabled/disabled) and whether check box will appear next to item name when action is taken.
|
||||
|
||||
### SetConfiguration
|
||||
|
||||
```cpp
|
||||
virtual void SetConfiguration(PowertoyModuleIface* module, const std::vector<ItemInfo>& config) = 0;
|
||||
```
|
||||
|
||||
Module should use this interface to inform system menu helper class which custom system menu items to create.
|
||||
|
||||
### ProcessSelectedItem
|
||||
|
||||
```cpp
|
||||
virtual void ProcessSelectedItem(PowertoyModuleIface* module, HWND window, const wchar_t* itemName) = 0;
|
||||
```
|
||||
|
||||
Process action taken on specific system menu item.
|
||||
|
||||
## Code organization
|
||||
|
||||
#### [`powertoy_module_interface.h`](./powertoy_module_interface.h)
|
||||
Contains the PowerToys interface definition.
|
||||
|
||||
### [`powertoy_system_menu.h`](./powertoy_system_module.h)
|
||||
Contains the PowerToys system menu helper interface definition.
|
||||
|
||||
#### [`lowlevel_keyboard_event_data.h`](./lowlevel_keyboard_event_data.h)
|
||||
Contains the `LowlevelKeyboardEvent` structure that's passed to `signal_event` for `ll_keyboard` events.
|
||||
|
||||
|
@ -28,6 +28,8 @@
|
||||
- unload the DLL.
|
||||
*/
|
||||
|
||||
class PowertoySystemMenuIface;
|
||||
|
||||
class PowertoyModuleIface {
|
||||
public:
|
||||
/* Returns the name of the PowerToy, this will be cached by the runner. */
|
||||
@ -63,6 +65,12 @@ public:
|
||||
* win_hook_event: see win_hook_event_data.h
|
||||
*/
|
||||
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) = 0;
|
||||
|
||||
/* Register helper class to handle system menu items related actions. */
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) = 0;
|
||||
/* Handle action on system menu item. */
|
||||
virtual void signal_system_menu_action(const wchar_t* name) = 0;
|
||||
|
||||
/* Destroy the PowerToy and free all memory. */
|
||||
virtual void destroy() = 0;
|
||||
};
|
||||
|
22
src/modules/interface/powertoy_system_menu.h
Normal file
22
src/modules/interface/powertoy_system_menu.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class PowertoyModuleIface;
|
||||
|
||||
class PowertoySystemMenuIface {
|
||||
public:
|
||||
struct ItemInfo {
|
||||
std::wstring name{};
|
||||
bool enable{ false };
|
||||
bool checkBox{ false };
|
||||
};
|
||||
/*
|
||||
* Set configuration of system menu items for specific powertoy module. Configuration
|
||||
* parameters include item name (and hotkey), item status at creation (enabled/disabled)
|
||||
* and whether check box will appear next to item name when action is taken.
|
||||
*/
|
||||
virtual void SetConfiguration(PowertoyModuleIface* module, const std::vector<ItemInfo>& config) = 0;
|
||||
/* Process action on specific system menu item. */
|
||||
virtual void ProcessSelectedItem(PowertoyModuleIface* module, HWND window, const wchar_t* itemName) = 0;
|
||||
};
|
@ -227,6 +227,9 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override { }
|
||||
virtual void signal_system_menu_action(const wchar_t* name) override { }
|
||||
|
||||
// Destroy the powertoy and free memory
|
||||
virtual void destroy() override
|
||||
{
|
||||
|
@ -21,6 +21,9 @@ public:
|
||||
virtual bool is_enabled() override;
|
||||
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override;
|
||||
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override { }
|
||||
virtual void signal_system_menu_action(const wchar_t* name) override { }
|
||||
|
||||
void on_held();
|
||||
void on_held_press(DWORD vkCode);
|
||||
void quick_hide();
|
||||
|
@ -20,5 +20,6 @@ PowertoyModule load_powertoy(const std::wstring& filename) {
|
||||
FreeLibrary(handle);
|
||||
winrt::throw_last_error();
|
||||
}
|
||||
module->register_system_menu_helper(&SystemMenuHelperInstace());
|
||||
return PowertoyModule(module, handle);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "powertoys_events.h"
|
||||
#include "system_menu_helper.h"
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
@ -12,6 +13,7 @@ class PowertoyModule;
|
||||
struct PowertoyModuleDeleter {
|
||||
void operator()(PowertoyModuleIface* module) const {
|
||||
if (module) {
|
||||
powertoys_events().unregister_system_menu_action(module);
|
||||
powertoys_events().unregister_receiver(module);
|
||||
module->destroy();
|
||||
}
|
||||
@ -38,6 +40,9 @@ public:
|
||||
powertoys_events().register_receiver(*want_signals, module);
|
||||
}
|
||||
}
|
||||
if (SystemMenuHelperInstace().HasCustomConfig(module)) {
|
||||
powertoys_events().register_system_menu_action(module);
|
||||
}
|
||||
}
|
||||
|
||||
const std::wstring& get_name() const {
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "powertoys_events.h"
|
||||
#include "lowlevel_keyboard_event.h"
|
||||
#include "win_hook_event.h"
|
||||
#include "system_menu_helper.h"
|
||||
|
||||
void first_subscribed(const std::wstring& event) {
|
||||
if (event == ll_keyboard)
|
||||
@ -41,6 +42,37 @@ void PowertoysEvents::unregister_receiver(PowertoyModuleIface* module) {
|
||||
}
|
||||
}
|
||||
|
||||
void PowertoysEvents::register_system_menu_action(PowertoyModuleIface* module) {
|
||||
std::unique_lock lock(mutex);
|
||||
system_menu_receivers.insert(module);
|
||||
}
|
||||
|
||||
void PowertoysEvents::unregister_system_menu_action(PowertoyModuleIface* module) {
|
||||
std::unique_lock lock(mutex);
|
||||
auto it = system_menu_receivers.find(module);
|
||||
if (it != system_menu_receivers.end()) {
|
||||
SystemMenuHelperInstace().Reset(module);
|
||||
system_menu_receivers.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void PowertoysEvents::handle_system_menu_action(const WinHookEvent& data) {
|
||||
if (data.event == EVENT_SYSTEM_MENUSTART) {
|
||||
for (auto& module : system_menu_receivers) {
|
||||
SystemMenuHelperInstace().Customize(module, data.hwnd);
|
||||
}
|
||||
}
|
||||
else if (data.event == EVENT_OBJECT_INVOKED) {
|
||||
if (PowertoyModuleIface* module{ SystemMenuHelperInstace().ModuleFromItemId(data.idChild) }) {
|
||||
std::wstring itemName = SystemMenuHelperInstace().ItemNameFromItemId(data.idChild);
|
||||
// Process event on specified system menu item by responsible module.
|
||||
module->signal_system_menu_action(itemName.c_str());
|
||||
// Process event on specified system menu item by system menu helper (check/uncheck if needed).
|
||||
SystemMenuHelperInstace().ProcessSelectedItem(module, GetForegroundWindow(), itemName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
intptr_t PowertoysEvents::signal_event(const std::wstring & event, intptr_t data) {
|
||||
intptr_t rvalue = 0;
|
||||
std::shared_lock lock(mutex);
|
||||
|
@ -1,15 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <interface/win_hook_event_data.h>
|
||||
#include <string>
|
||||
|
||||
class PowertoysEvents {
|
||||
public:
|
||||
void register_receiver(const std::wstring& event, PowertoyModuleIface* module);
|
||||
void unregister_receiver(PowertoyModuleIface* module);
|
||||
|
||||
void register_system_menu_action(PowertoyModuleIface* module);
|
||||
void unregister_system_menu_action(PowertoyModuleIface* module);
|
||||
void handle_system_menu_action(const WinHookEvent& data);
|
||||
|
||||
intptr_t signal_event(const std::wstring& event, intptr_t data);
|
||||
private:
|
||||
std::shared_mutex mutex;
|
||||
std::unordered_map<std::wstring, std::vector<PowertoyModuleIface*>> receivers;
|
||||
std::unordered_set<PowertoyModuleIface*> system_menu_receivers;
|
||||
};
|
||||
|
||||
PowertoysEvents& powertoys_events();
|
||||
|
@ -107,6 +107,7 @@
|
||||
<ClCompile Include="powertoy_module.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="settings_window.cpp" />
|
||||
<ClCompile Include="system_menu_helper.cpp" />
|
||||
<ClCompile Include="trace.cpp" />
|
||||
<ClCompile Include="tray_icon.cpp" />
|
||||
<ClCompile Include="unhandled_exception_handler.cpp" />
|
||||
@ -121,6 +122,7 @@
|
||||
<ClInclude Include="powertoy_module.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="settings_window.h" />
|
||||
<ClInclude Include="system_menu_helper.h" />
|
||||
<ClInclude Include="trace.h" />
|
||||
<ClInclude Include="tray_icon.h" />
|
||||
<ClInclude Include="unhandled_exception_handler.h" />
|
||||
|
@ -33,6 +33,9 @@
|
||||
<ClCompile Include="win_hook_event.cpp">
|
||||
<Filter>Events</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="system_menu_helper.cpp">
|
||||
<Filter>Utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
@ -67,6 +70,9 @@
|
||||
<ClInclude Include="win_hook_event.h">
|
||||
<Filter>Events</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="system_menu_helper.h">
|
||||
<Filter>Utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Utils">
|
||||
|
129
src/runner/system_menu_helper.cpp
Normal file
129
src/runner/system_menu_helper.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
#include "pch.h"
|
||||
#include "system_menu_helper.h"
|
||||
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
|
||||
namespace {
|
||||
constexpr int KSeparatorPos = 1;
|
||||
constexpr int KNewItemPos = 2;
|
||||
|
||||
unsigned int GenerateItemId() {
|
||||
static unsigned int generator = 0x70777479;
|
||||
return ++generator;
|
||||
}
|
||||
}
|
||||
|
||||
SystemMenuHelper& SystemMenuHelperInstace() {
|
||||
static SystemMenuHelper instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void SystemMenuHelper::SetConfiguration(PowertoyModuleIface* module, const std::vector<ItemInfo>& config) {
|
||||
Reset(module);
|
||||
Configurations[module] = config;
|
||||
for (auto& [window, modules] : ProcessedModules) {
|
||||
// Unregister module. After system menu is opened again, new configuration will be applied.
|
||||
modules.erase(std::remove(std::begin(modules), std::end(modules), module), std::end(modules));
|
||||
}
|
||||
}
|
||||
|
||||
void SystemMenuHelper::ProcessSelectedItem(PowertoyModuleIface* module, HWND window, const wchar_t* itemName) {
|
||||
for (const auto& item : Configurations[module]) {
|
||||
if (itemName == item.name && item.checkBox) {
|
||||
// Handle check/uncheck action only if specified by module configuration.
|
||||
for (const auto& [id, data] : IdMappings) {
|
||||
if (data.second == itemName) {
|
||||
HMENU systemMenu = GetSystemMenu(window, false);
|
||||
int state = (GetMenuState(systemMenu, id, MF_BYCOMMAND) == MF_CHECKED) ? MF_UNCHECKED : MF_CHECKED;
|
||||
CheckMenuItem(systemMenu, id, MF_BYCOMMAND | state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SystemMenuHelper::Customize(PowertoyModuleIface* module, HWND window) {
|
||||
auto& modules = ProcessedModules[window];
|
||||
for (const auto& m : modules) {
|
||||
if (module == m) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
AddSeparator(module, window);
|
||||
for (const auto& info : Configurations[module]) {
|
||||
AddItem(module, window, info.name, info.enable);
|
||||
}
|
||||
modules.push_back(module);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SystemMenuHelper::Reset(PowertoyModuleIface* module) {
|
||||
for (auto& [window, modules] : ProcessedModules) {
|
||||
if (HMENU systemMenu{ GetSystemMenu(window, false) }) {
|
||||
for (auto& [id, data] : IdMappings) {
|
||||
if (data.first == module) {
|
||||
DeleteMenu(systemMenu, id, MF_BYCOMMAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SystemMenuHelper::HasCustomConfig(PowertoyModuleIface* module) {
|
||||
return Configurations.find(module) != Configurations.end();
|
||||
}
|
||||
|
||||
bool SystemMenuHelper::AddItem(PowertoyModuleIface* module, HWND window, const std::wstring& name, const bool enable) {
|
||||
if (HMENU systemMenu{ GetSystemMenu(window, false) }) {
|
||||
MENUITEMINFO item;
|
||||
item.cbSize = sizeof(item);
|
||||
item.fMask = MIIM_ID | MIIM_STRING | MIIM_STATE;
|
||||
item.fState = MF_UNCHECKED | MF_DISABLED; // Item is disabled by default.
|
||||
item.wID = GenerateItemId();
|
||||
item.dwTypeData = const_cast<WCHAR*>(name.c_str());
|
||||
item.cch = name.size() + 1;
|
||||
|
||||
if (InsertMenuItem(systemMenu, GetMenuItemCount(systemMenu) - KNewItemPos, true, &item)) {
|
||||
IdMappings[item.wID] = { module, name };
|
||||
if (enable) {
|
||||
EnableMenuItem(systemMenu, item.wID, MF_BYCOMMAND | MF_ENABLED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SystemMenuHelper::AddSeparator(PowertoyModuleIface* module, HWND window) {
|
||||
if (HMENU systemMenu{ GetSystemMenu(window, false) }) {
|
||||
MENUITEMINFO separator;
|
||||
separator.cbSize = sizeof(separator);
|
||||
separator.fMask = MIIM_ID | MIIM_FTYPE;
|
||||
separator.fType = MFT_SEPARATOR;
|
||||
separator.wID = GenerateItemId();
|
||||
|
||||
if (InsertMenuItem(systemMenu, GetMenuItemCount(systemMenu) - KSeparatorPos, true, &separator)) {
|
||||
IdMappings[separator.wID] = { module, L"sepparator_dummy_name" };
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PowertoyModuleIface* SystemMenuHelper::ModuleFromItemId(const int& id) {
|
||||
auto it = IdMappings.find(id);
|
||||
if (it != IdMappings.end()) {
|
||||
return it->second.first;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::wstring SystemMenuHelper::ItemNameFromItemId(const int& id) {
|
||||
auto itemIt = IdMappings.find(id);
|
||||
if (itemIt != IdMappings.end()) {
|
||||
return itemIt->second.second;
|
||||
}
|
||||
return std::wstring{};
|
||||
}
|
42
src/runner/system_menu_helper.h
Normal file
42
src/runner/system_menu_helper.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <interface/powertoy_system_menu.h>
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
class PowertoyModuleIface;
|
||||
|
||||
class SystemMenuHelper : public PowertoySystemMenuIface {
|
||||
public:
|
||||
// PowertoySystemMenuIface
|
||||
virtual void SetConfiguration(PowertoyModuleIface* module, const std::vector<ItemInfo>& config) override;
|
||||
virtual void ProcessSelectedItem(PowertoyModuleIface* module, HWND window, const wchar_t* itemName) override;
|
||||
|
||||
bool Customize(PowertoyModuleIface* module, HWND window);
|
||||
void Reset(PowertoyModuleIface* module);
|
||||
|
||||
bool HasCustomConfig(PowertoyModuleIface* module);
|
||||
|
||||
PowertoyModuleIface* ModuleFromItemId(const int& id);
|
||||
const std::wstring ItemNameFromItemId(const int& id);
|
||||
|
||||
private:
|
||||
bool AddItem(PowertoyModuleIface* module, HWND window, const std::wstring& name, const bool enable);
|
||||
bool AddSeparator(PowertoyModuleIface* module, HWND window);
|
||||
|
||||
// Store processed modules per window to avoid handling it multiple times.
|
||||
std::unordered_map<HWND, std::vector<PowertoyModuleIface*>> ProcessedModules{};
|
||||
|
||||
// Keep mappings form item id to the module who created it and item name for faster processing later.
|
||||
std::unordered_map<int, std::pair<PowertoyModuleIface*, std::wstring>> IdMappings{};
|
||||
|
||||
// Store configurations provided by module.
|
||||
// This will be used to create custom system menu items and to handle updates.
|
||||
std::unordered_map<PowertoyModuleIface*, std::vector<ItemInfo>> Configurations{};
|
||||
};
|
||||
|
||||
SystemMenuHelper& SystemMenuHelperInstace();
|
@ -9,6 +9,8 @@ static std::mutex mutex;
|
||||
static std::deque<WinHookEvent> hook_events;
|
||||
static std::condition_variable dispatch_cv;
|
||||
|
||||
void intercept_system_menu_action(intptr_t);
|
||||
|
||||
static void CALLBACK win_hook_event_proc(HWINEVENTHOOK winEventHook,
|
||||
DWORD event,
|
||||
HWND window,
|
||||
@ -39,7 +41,9 @@ static void dispatch_thread_proc() {
|
||||
auto event = hook_events.front();
|
||||
hook_events.pop_front();
|
||||
lock.unlock();
|
||||
powertoys_events().signal_event(win_hook_event, reinterpret_cast<intptr_t>(&event));
|
||||
intptr_t data = reinterpret_cast<intptr_t>(&event);
|
||||
intercept_system_menu_action(data);
|
||||
powertoys_events().signal_event(win_hook_event, data);
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
@ -70,3 +74,9 @@ void stop_win_hook_event() {
|
||||
hook_events.shrink_to_fit();
|
||||
}
|
||||
|
||||
void intercept_system_menu_action(intptr_t data) {
|
||||
WinHookEvent* evt = reinterpret_cast<WinHookEvent*>(data);
|
||||
if (evt->event == EVENT_SYSTEM_MENUSTART || evt->event == EVENT_OBJECT_INVOKED) {
|
||||
powertoys_events().handle_system_menu_action(*evt);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user