PowerToys interface: remove powertoys events and system_menu_helper functionality (#5323)

This commit is contained in:
Andrey Nekrasov
2020-07-31 14:06:13 +03:00
committed by GitHub
parent cff654ae69
commit 49b56d9b52
42 changed files with 116 additions and 1163 deletions

View File

@@ -11,9 +11,6 @@ public:
virtual void enable() = 0;
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;
};
@@ -28,7 +25,6 @@ The PowerToys runner will, for each PowerToy DLL:
On the received object, the runner will call:
- [`get_name()`](#get_name) to get the name of the PowerToy,
- [`get_events()`](#get_events) to get the list of the events the PowerToy wants to subscribe to,
- [`enable()`](#enable) to initialize the PowerToy.
While running, the runner might call the following methods between create_powertoy()
@@ -37,9 +33,6 @@ and destroy():
- [`get_config()`](#get_config) to get the available configuration settings,
- [`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),
@@ -75,18 +68,6 @@ virtual const wchar_t* get_name()
Returns the name of the PowerToy, it will be cached by the runner.
## get_events
```cpp
virtual const wchar_t** get_events()
```
Returns a null-terminated table of the names of the events the PowerToy wants to subscribe to. Available events:
* ll_keyboard
* win_hook_event
A nullptr can be returned to signal that the PowerToy does not want to subscribe to any event.
## get_config
```
@@ -140,38 +121,6 @@ Disables the PowerToy, should free as much memory as possible.
Returns the PowerToy state.
## signal_event
```cpp
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) = 0;
```
Handle event. Only the events the PowerToy subscribed to will be signaled.
The data argument and return value meaning are event-specific:
* ll_keyboard: see [`lowlevel_keyboard_event_data.h`](./lowlevel_keyboard_event_data.h).
* win_hook_event: see [`win_hook_event_data.h`](./win_hook_event_data.h)
Please note that some of the events are currently being signalled from a separate thread.
## 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
@@ -179,62 +128,7 @@ Item name is passed as an argument, so that module can distinguish between diffe
```
Destroy the PowerToy and free all memory.
## 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`](/src/modules/interface/powertoy_module_interface.h)
Contains the PowerToys interface definition.
### [`powertoy_system_menu.h`](/src/modules/interface/powertoy_system_module.h)
Contains the PowerToys system menu helper interface definition.
### [`lowlevel_keyboard_event_data.h`](/src/modules/interface/lowlevel_keyboard_event_data.h)
Contains the `LowlevelKeyboardEvent` structure that's passed to `signal_event` for `ll_keyboard` events.
### [`win_hook_event_data.h`](/src/modules/interface/win_hook_event_data.h)
Contains the `WinHookEvent` structure that's passed to `signal_event` for `win_hook_event` events.

View File

@@ -1,85 +0,0 @@
# Shared hooks
To minimize the performance impact on the machine only `runner` installs global hooks, passing the events to registered callbacks in each PowerToy module.
When a PowerToy module is loaded, the `runner` calls the [`get_events()`](/src/modules/interface/powertoy_module_interface.h#L40) method to get a NULL-terminated array of NULL-terminated strings with the names of the events that the PowerToy wants to subscribe to. A `const wchar_t*` string is provided for each of the event names.
Events are signalled by the `runner` calling the [`signal_event(name, data)`](/src/modules/interface/powertoy_module_interface.h#L53) method of the PowerToy module. The `name` parameter contains the NULL-terminated name of the event. The `data` parameter and the method return value are specific for each event.
Currently supported hooks:
* `"ll_keyboard"` - [Low Level Keyboard Hook](#low-level-keyboard-hook)
* `"win_hook_event"` - [Windows Event Hook](#windows-event-hook)
## Low Level Keyboard Hook
This event is signaled whenever the user presses or releases a key on the keyboard. To subscribe to this event, add `"ll_keyboard"` to the table returned by the `get_events()` method.
The PowerToys runner installs low-level keyboard hook using `SetWindowsHookEx(WH_KEYBOARD_LL, ...)`. See [this MSDN page](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644985(v%3Dvs.85)) for details.
When a keyboard event is signaled and `ncCode` equals `HC_ACTION`, the `wParam` and `lParam` event parameters are passed to all subscribed clients in the [`LowlevelKeyboardEvent`](/src/modules/interface/lowlevel_keyboard_event_data.h#L38-L41) struct.
The `intptr_t data` event argument is a pointer to the `LowlevelKeyboardEvent` struct.
A non-zero return value from any of the subscribed PowerToys will cause the runner hook proc to return 1, thus swallowing the keyboard event.
Example usage, that makes Windows ignore the L key:
```c++
virtual const wchar_t** get_events() override {
static const wchar_t* events[2] = { ll_keyboard,
nullptr };
return events;
}
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override {
if (wcscmp(name, ll_keyboard) == 0) {
auto& event = *(reinterpret_cast<LowlevelKeyboardEvent*>(data));
// The L key has vkCode of 0x4C, see:
// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
if (event.wParam == WM_KEYDOWN && event.lParam->vkCode == 0x4C) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
```
## Windows Event Hook
This event is signaled for [a range of events](https://docs.microsoft.com/pl-pl/windows/win32/winauto/event-constants). To subscribe to this event, add `"win_hook_event"` to the table returned by the `get_events()` method. See [this MSDN doc](https://docs.microsoft.com/pl-pl/windows/win32/api/winuser/nf-winuser-setwineventhook) for details.
The `intptr_t data` event argument is a pointer to the [`WinHookEvent`](/src/modules/interface/win_hook_event_data.h#L43-L50) struct.
The return value of the event handler is ignored.
Example usage, that detects a window being resized:
```c++
virtual const wchar_t** get_events() override {
static const wchar_t* events[2] = { win_hook_event,
nullptr };
return events;
}
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override {
if (wcscmp(name, win_hook_event) == 0) {
auto& event = *(reinterpret_cast<WinHookEvent*>(data));
switch (event.event) {
case EVENT_SYSTEM_MOVESIZESTART:
size_start(event.hwnd);
break;
case EVENT_SYSTEM_MOVESIZEEND:
size_end(event.hwnd);
break;
default:
break;
}
}
return 0;
}
```
Taking too long to process the events has negative impact on the whole system performance. To address this, the events are signaled from a different thread, not from the event hook callback itself.