mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-01-18 14:41:21 +08:00
PowerToys interface: remove powertoys events and system_menu_helper functionality (#5323)
This commit is contained in:
parent
cff654ae69
commit
49b56d9b52
@ -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.
|
||||
|
||||
|
@ -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.
|
9
src/common/LowlevelKeyboardEvent.h
Normal file
9
src/common/LowlevelKeyboardEvent.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
struct LowlevelKeyboardEvent
|
||||
{
|
||||
KBDLLHOOKSTRUCT* lParam;
|
||||
WPARAM wParam;
|
||||
};
|
14
src/common/WinHookEvent.h
Normal file
14
src/common/WinHookEvent.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
struct WinHookEvent
|
||||
{
|
||||
DWORD event;
|
||||
HWND hwnd;
|
||||
LONG idObject;
|
||||
LONG idChild;
|
||||
DWORD idEventThread;
|
||||
DWORD dwmsEventTime;
|
||||
};
|
@ -128,6 +128,7 @@
|
||||
<ClInclude Include="com_object_factory.h" />
|
||||
<ClInclude Include="keyboard_layout.h" />
|
||||
<ClInclude Include="keyboard_layout_impl.h" />
|
||||
<ClInclude Include="LowlevelKeyboardEvent.h" />
|
||||
<ClInclude Include="notifications.h" />
|
||||
<ClInclude Include="processApi.h" />
|
||||
<ClInclude Include="RcResource.h" />
|
||||
@ -153,6 +154,7 @@
|
||||
<ClInclude Include="two_way_pipe_message_ipc_impl.h" />
|
||||
<ClInclude Include="version.h" />
|
||||
<ClInclude Include="windows_colors.h" />
|
||||
<ClInclude Include="WinHookEvent.h" />
|
||||
<ClInclude Include="winstore.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -129,6 +129,12 @@
|
||||
<ClInclude Include="processApi.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LowlevelKeyboardEvent.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WinHookEvent.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="d2d_svg.cpp">
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "keyboard_layout.h"
|
||||
#include "..\modules\interface\lowlevel_keyboard_event_data.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
@ -9,10 +9,9 @@
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
BOOL APIENTRY DllMain(HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
@ -27,7 +26,8 @@ BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct ModuleSettings{
|
||||
struct ModuleSettings
|
||||
{
|
||||
} g_settings;
|
||||
|
||||
class ColorPicker : public PowertoyModuleIface
|
||||
@ -39,8 +39,9 @@ private:
|
||||
|
||||
HANDLE m_hProcess;
|
||||
|
||||
// Time to wait for process to close after sending WM_CLOSE signal
|
||||
// Time to wait for process to close after sending WM_CLOSE signal
|
||||
static const int MAX_WAIT_MILLISEC = 10000;
|
||||
|
||||
public:
|
||||
ColorPicker()
|
||||
{
|
||||
@ -67,13 +68,6 @@ public:
|
||||
return app_name.c_str();
|
||||
}
|
||||
|
||||
virtual const wchar_t** get_events() override
|
||||
{
|
||||
static const wchar_t* events[] = { nullptr };
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
|
||||
{
|
||||
HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
|
||||
@ -111,8 +105,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void enable(){
|
||||
|
||||
virtual void enable()
|
||||
{
|
||||
// use only with new settings?
|
||||
if (UseNewSettings())
|
||||
{
|
||||
@ -134,12 +128,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
virtual void disable() {
|
||||
virtual void disable()
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
terminateProcess();
|
||||
}
|
||||
|
||||
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
@ -148,11 +143,6 @@ public:
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK requestMainWindowClose(HWND nextWindow, LPARAM closePid)
|
||||
{
|
||||
DWORD windowPid;
|
||||
@ -174,15 +164,9 @@ public:
|
||||
TerminateProcess(m_hProcess, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register helper class to handle system menu items related actions. */
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) {}
|
||||
/* Handle action on system menu item. */
|
||||
virtual void signal_system_menu_action(const wchar_t* name) {}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
{
|
||||
return new ColorPicker();
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,8 @@
|
||||
#include <common/settings_objects.h>
|
||||
#include <common/common.h>
|
||||
#include <common/debug_control.h>
|
||||
#include <common/LowlevelKeyboardEvent.h>
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
#include <interface/win_hook_event_data.h>
|
||||
#include <lib/ZoneSet.h>
|
||||
|
||||
#include <lib/resource.h>
|
||||
@ -44,13 +43,6 @@ public:
|
||||
return app_name.c_str();
|
||||
}
|
||||
|
||||
// Return array of the names of all events that this powertoy listens for, with
|
||||
// nullptr as the last element of the array. Nullptr can also be returned for empty list.
|
||||
virtual PCWSTR* get_events() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return JSON with the configuration options.
|
||||
// These are the settings shown on the settings page along with their current values.
|
||||
virtual bool get_config(_Out_ PWSTR buffer, _Out_ int* buffer_size) override
|
||||
@ -134,15 +126,6 @@ public:
|
||||
return (m_app != nullptr);
|
||||
}
|
||||
|
||||
// PowertoyModuleIface method, unused
|
||||
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "VirtualDesktopUtils.h"
|
||||
#include "MonitorWorkAreaHandler.h"
|
||||
|
||||
#include <interface/win_hook_event_data.h>
|
||||
#include <lib/SecondaryMouseButtonsHook.h>
|
||||
#include <lib/GenericKeyHook.h>
|
||||
|
||||
@ -365,7 +364,8 @@ bool FancyZones::ShouldProcessNewWindow(HWND window) noexcept
|
||||
}
|
||||
|
||||
std::vector<int> FancyZones::GetZoneIndexSetFromWorkAreaHistory(
|
||||
HWND window, winrt::com_ptr<IZoneWindow> workArea) noexcept
|
||||
HWND window,
|
||||
winrt::com_ptr<IZoneWindow> workArea) noexcept
|
||||
{
|
||||
const auto activeZoneSet = workArea->ActiveZoneSet();
|
||||
if (activeZoneSet)
|
||||
@ -458,9 +458,9 @@ RECT FitOnScreen(const RECT& windowRect, const RECT& originMonitorRect, const RE
|
||||
H = min(H, RectHeight(destMonitorRect) - CUSTOM_POSITIONING_LEFT_TOP_PADDING);
|
||||
}
|
||||
|
||||
return { .left = left,
|
||||
.top = top,
|
||||
.right = left + W,
|
||||
return { .left = left,
|
||||
.top = top,
|
||||
.right = left + W,
|
||||
.bottom = top + H };
|
||||
}
|
||||
|
||||
@ -506,7 +506,7 @@ FancyZones::WindowCreated(HWND window) noexcept
|
||||
// creation of new window. We need to check if window being processed is on currently active desktop.
|
||||
return;
|
||||
}
|
||||
const bool moveToAppLastZone = m_settings->GetSettings()->appLastZone_moveWindows;
|
||||
const bool moveToAppLastZone = m_settings->GetSettings()->appLastZone_moveWindows;
|
||||
const bool openOnActiveMonitor = m_settings->GetSettings()->openWindowOnActiveMonitor;
|
||||
if ((moveToAppLastZone || openOnActiveMonitor) && ShouldProcessNewWindow(window))
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/WinHookEvent.h>
|
||||
|
||||
interface IZoneWindow;
|
||||
interface IFancyZonesSettings;
|
||||
interface IZoneSet;
|
||||
@ -11,11 +13,13 @@ interface __declspec(uuid("{50D3F0F5-736E-4186-BDF4-3D6BEE150C3A}")) IFancyZones
|
||||
/**
|
||||
* Start and initialize FancyZones.
|
||||
*/
|
||||
IFACEMETHOD_(void, Run)() = 0;
|
||||
IFACEMETHOD_(void, Run)
|
||||
() = 0;
|
||||
/**
|
||||
* Stop FancyZones and do the clean up.
|
||||
*/
|
||||
IFACEMETHOD_(void, Destroy)() = 0;
|
||||
IFACEMETHOD_(void, Destroy)
|
||||
() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -26,13 +30,15 @@ interface __declspec(uuid("{2CB37E8F-87E6-4AEC-B4B2-E0FDC873343F}")) IFancyZones
|
||||
/**
|
||||
* Inform FancyZones that user has switched between virtual desktops.
|
||||
*/
|
||||
IFACEMETHOD_(void, VirtualDesktopChanged)() = 0;
|
||||
IFACEMETHOD_(void, VirtualDesktopChanged)
|
||||
() = 0;
|
||||
/**
|
||||
* Callback from WinEventHook to FancyZones
|
||||
*
|
||||
* @param data Handle of window being moved or resized.
|
||||
*/
|
||||
IFACEMETHOD_(void, HandleWinHookEvent)(const WinHookEvent* data) = 0;
|
||||
IFACEMETHOD_(void, HandleWinHookEvent)
|
||||
(const WinHookEvent* data) = 0;
|
||||
/**
|
||||
* Process keyboard event.
|
||||
*
|
||||
@ -40,15 +46,18 @@ interface __declspec(uuid("{2CB37E8F-87E6-4AEC-B4B2-E0FDC873343F}")) IFancyZones
|
||||
* @returns Boolean indicating if this event should be passed on further to other applications
|
||||
* in event chain, or should it be suppressed.
|
||||
*/
|
||||
IFACEMETHOD_(bool, OnKeyDown)(PKBDLLHOOKSTRUCT info) = 0;
|
||||
IFACEMETHOD_(bool, OnKeyDown)
|
||||
(PKBDLLHOOKSTRUCT info) = 0;
|
||||
/**
|
||||
* Toggle FancyZones editor application.
|
||||
*/
|
||||
IFACEMETHOD_(void, ToggleEditor)() = 0;
|
||||
IFACEMETHOD_(void, ToggleEditor)
|
||||
() = 0;
|
||||
/**
|
||||
* Callback triggered when user changes FancyZones settings.
|
||||
*/
|
||||
IFACEMETHOD_(void, SettingsChanged)() = 0;
|
||||
IFACEMETHOD_(void, SettingsChanged)
|
||||
() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -59,31 +68,38 @@ interface __declspec(uuid("{5C8D99D6-34B2-4F4A-A8E5-7483F6869775}")) IZoneWindow
|
||||
/**
|
||||
* Assign window to appropriate zone inside new zone layout.
|
||||
*/
|
||||
IFACEMETHOD_(void, MoveWindowsOnActiveZoneSetChange)() = 0;
|
||||
/**
|
||||
IFACEMETHOD_(void, MoveWindowsOnActiveZoneSetChange)
|
||||
() = 0;
|
||||
/**
|
||||
* @returns Basic zone color.
|
||||
*/
|
||||
IFACEMETHOD_(COLORREF, GetZoneColor)() = 0;
|
||||
/**
|
||||
IFACEMETHOD_(COLORREF, GetZoneColor)
|
||||
() = 0;
|
||||
/**
|
||||
* @returns Zone border color.
|
||||
*/
|
||||
IFACEMETHOD_(COLORREF, GetZoneBorderColor)() = 0;
|
||||
IFACEMETHOD_(COLORREF, GetZoneBorderColor)
|
||||
() = 0;
|
||||
/**
|
||||
* @returns Color used to highlight zone while giving zone layout hints.
|
||||
*/
|
||||
IFACEMETHOD_(COLORREF, GetZoneHighlightColor)() = 0;
|
||||
IFACEMETHOD_(COLORREF, GetZoneHighlightColor)
|
||||
() = 0;
|
||||
/**
|
||||
* @returns Integer in range [0, 100] indicating opacity of highlighted zone (while giving zone layout hints).
|
||||
*/
|
||||
IFACEMETHOD_(int, GetZoneHighlightOpacity)() = 0;
|
||||
IFACEMETHOD_(int, GetZoneHighlightOpacity)
|
||||
() = 0;
|
||||
/**
|
||||
* @returns Boolean indicating if dragged window should be transparent.
|
||||
*/
|
||||
IFACEMETHOD_(bool, isMakeDraggedWindowTransparentActive) () = 0;
|
||||
IFACEMETHOD_(bool, isMakeDraggedWindowTransparentActive)
|
||||
() = 0;
|
||||
/**
|
||||
* @returns Boolean indicating if move/size operation is currently active.
|
||||
*/
|
||||
IFACEMETHOD_(bool, InMoveSize) () = 0;
|
||||
IFACEMETHOD_(bool, InMoveSize)
|
||||
() = 0;
|
||||
};
|
||||
|
||||
winrt::com_ptr<IFancyZones> MakeFancyZones(HINSTANCE hinstance, const winrt::com_ptr<IFancyZonesSettings>& settings) noexcept;
|
||||
|
@ -53,15 +53,6 @@ public:
|
||||
return app_name.c_str();
|
||||
}
|
||||
|
||||
// Return array of the names of all events that this powertoy listens for, with
|
||||
// nullptr as the last element of the array. Nullptr can also be returned for empty
|
||||
// list.
|
||||
virtual const wchar_t** get_events() override
|
||||
{
|
||||
static const wchar_t* events[] = { nullptr };
|
||||
return events;
|
||||
}
|
||||
|
||||
// Return JSON with the configuration options.
|
||||
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
|
||||
{
|
||||
@ -104,15 +95,6 @@ public:
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
// Handle incoming event, data is event-specific
|
||||
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override {}
|
||||
virtual void signal_system_menu_action(const wchar_t* name) override {}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
|
@ -1,45 +0,0 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
|
||||
/*
|
||||
ll_keyboard - Lowlevel Keyboard Hook
|
||||
|
||||
The PowerToys runner installs low-level keyboard hook using
|
||||
SetWindowsHookEx(WH_KEYBOARD_LL, ...)
|
||||
See 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 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:
|
||||
|
||||
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
|
||||
if (event.wParam == WM_KEYDOWN && event.lParam->vkCode == 0x4C) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
namespace {
|
||||
const wchar_t* ll_keyboard = L"ll_keyboard";
|
||||
}
|
||||
|
||||
struct LowlevelKeyboardEvent {
|
||||
KBDLLHOOKSTRUCT* lParam;
|
||||
WPARAM wParam;
|
||||
};
|
@ -12,7 +12,6 @@
|
||||
|
||||
On the received object, the runner will call:
|
||||
- get_name() to get the name of the PowerToy,
|
||||
- get_events() to get the list of the events the PowerToy wants to subscribe to,
|
||||
- enable() to initialize the PowerToy.
|
||||
|
||||
While running, the runner might call the following methods between create_powertoy()
|
||||
@ -21,58 +20,35 @@
|
||||
- get_config() to get the available configuration settings,
|
||||
- set_config() to set various settings,
|
||||
- call_custom_action() when the user selects clicks a custom action in settings,
|
||||
- signal_event() to send an event the PowerToy registered to.
|
||||
|
||||
When terminating, the runner will:
|
||||
- call destroy() which should free all the memory and delete the PowerToy object,
|
||||
- unload the DLL.
|
||||
*/
|
||||
|
||||
class PowertoySystemMenuIface;
|
||||
|
||||
class PowertoyModuleIface {
|
||||
class PowertoyModuleIface
|
||||
{
|
||||
public:
|
||||
/* Returns the name of the PowerToy, this will be cached by the runner. */
|
||||
virtual const wchar_t* get_name() = 0;
|
||||
/* 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.
|
||||
*/
|
||||
virtual const wchar_t** get_events() = 0;
|
||||
/* Fills a buffer with the available configuration settings.
|
||||
* If 'buffer' is a null ptr or the buffer size is not large enough
|
||||
* sets the required buffer size in 'buffer_size' and return false.
|
||||
* Returns true if successful.
|
||||
*/
|
||||
virtual bool get_config(wchar_t* buffer, int *buffer_size) = 0;
|
||||
/* Sets the configuration values. */
|
||||
virtual void set_config(const wchar_t* config) = 0;
|
||||
/* Call custom action from settings screen. */
|
||||
virtual void call_custom_action(const wchar_t* action) {};
|
||||
/* Enables the PowerToy. */
|
||||
virtual void enable() = 0;
|
||||
/* Disables the PowerToy, should free as much memory as possible. */
|
||||
virtual void disable() = 0;
|
||||
/* Should return if the PowerToys is enabled or disabled. */
|
||||
virtual bool is_enabled() = 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.
|
||||
* 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;
|
||||
/* Returns the name of the PowerToy, this will be cached by the runner. */
|
||||
virtual const wchar_t* get_name() = 0;
|
||||
/* Fills a buffer with the available configuration settings.
|
||||
* If 'buffer' is a null ptr or the buffer size is not large enough
|
||||
* sets the required buffer size in 'buffer_size' and return false.
|
||||
* Returns true if successful.
|
||||
*/
|
||||
virtual bool get_config(wchar_t* buffer, int* buffer_size) = 0;
|
||||
/* Sets the configuration values. */
|
||||
virtual void set_config(const wchar_t* config) = 0;
|
||||
/* Call custom action from settings screen. */
|
||||
virtual void call_custom_action(const wchar_t* action){};
|
||||
/* Enables the PowerToy. */
|
||||
virtual void enable() = 0;
|
||||
/* Disables the PowerToy, should free as much memory as possible. */
|
||||
virtual void disable() = 0;
|
||||
/* Should return if the PowerToys is enabled or disabled. */
|
||||
virtual bool is_enabled() = 0;
|
||||
/* Destroy the PowerToy and free all memory. */
|
||||
virtual void destroy() = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -90,4 +66,4 @@ public:
|
||||
|
||||
In case of errors return nullptr.
|
||||
*/
|
||||
typedef PowertoyModuleIface* (__cdecl *powertoy_create_func)();
|
||||
typedef PowertoyModuleIface*(__cdecl* powertoy_create_func)();
|
||||
|
@ -1,22 +0,0 @@
|
||||
#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;
|
||||
};
|
@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
|
||||
/*
|
||||
win_hook_event - Windows Event Hook
|
||||
|
||||
The PowerToys runner installs event hook functions for a range of events. See
|
||||
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 struct.
|
||||
|
||||
The return value of the event handler is ignored.
|
||||
|
||||
Example usage, that detects a window being resized:
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
const wchar_t* win_hook_event = L"win_hook_event";
|
||||
}
|
||||
|
||||
struct WinHookEvent {
|
||||
DWORD event;
|
||||
HWND hwnd;
|
||||
LONG idObject;
|
||||
LONG idChild;
|
||||
DWORD idEventThread;
|
||||
DWORD dwmsEventTime;
|
||||
};
|
@ -3,8 +3,8 @@
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
|
||||
#include <LowlevelKeyboardEvent.h>
|
||||
// Available states for the KeyDelay state machine.
|
||||
enum class KeyDelayState
|
||||
{
|
||||
|
@ -2,8 +2,8 @@
|
||||
#include <mutex>
|
||||
#include "KeyboardManagerConstants.h"
|
||||
#include "../common/keyboard_layout.h"
|
||||
#include "../common/LowlevelKeyboardEvent.h"
|
||||
#include <functional>
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
#include <variant>
|
||||
#include "Shortcut.h"
|
||||
#include "RemapShortcut.h"
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include "Shortcut.h"
|
||||
#include "../common/keyboard_layout.h"
|
||||
#include "../common/shared_constants.h"
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
#include "Helpers.h"
|
||||
#include "InputInterface.h"
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include "keyboardmanager/common/KeyboardManagerConstants.h"
|
||||
|
||||
#include <common/LowlevelKeyboardEvent.h>
|
||||
|
||||
class InputInterface;
|
||||
class KeyboardManagerState;
|
||||
class Shortcut;
|
||||
|
@ -1,7 +1,5 @@
|
||||
#include "pch.h"
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
#include <interface/win_hook_event_data.h>
|
||||
#include <common/settings_objects.h>
|
||||
#include <common/shared_constants.h>
|
||||
#include "resource.h"
|
||||
@ -235,16 +233,6 @@ public:
|
||||
return app_name.c_str();
|
||||
}
|
||||
|
||||
// Return array of the names of all events that this powertoy listens for, with
|
||||
// nullptr as the last element of the array. Nullptr can also be returned for empty
|
||||
// list.
|
||||
virtual const wchar_t** get_events() override
|
||||
{
|
||||
static const wchar_t* events[] = { ll_keyboard, nullptr };
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
// Return JSON with the configuration options.
|
||||
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
|
||||
{
|
||||
@ -339,16 +327,6 @@ public:
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
// Handle incoming event, data is event-specific
|
||||
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override {}
|
||||
|
||||
virtual void signal_system_menu_action(const wchar_t* name) override {}
|
||||
|
||||
// Hook procedure definition
|
||||
static LRESULT CALLBACK hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
@ -2,7 +2,8 @@
|
||||
#include <keyboardmanager/common/InputInterface.h>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
|
||||
#include <common/LowlevelKeyboardEvent.h>
|
||||
|
||||
// Class for mocked keyboard input
|
||||
class MockedInput :
|
||||
|
@ -1,7 +1,5 @@
|
||||
#include "pch.h"
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
#include <interface/win_hook_event_data.h>
|
||||
#include <common/settings_objects.h>
|
||||
#include <common/common.h>
|
||||
#include "trace.h"
|
||||
@ -80,23 +78,6 @@ public:
|
||||
return app_name.c_str();
|
||||
}
|
||||
|
||||
// Return array of the names of all events that this powertoy listens for, with
|
||||
// nullptr as the last element of the array. Nullptr can also be returned for empty
|
||||
// list.
|
||||
virtual const wchar_t** get_events() override
|
||||
{
|
||||
static const wchar_t* events[] = { nullptr };
|
||||
// Available events:
|
||||
// - ll_keyboard
|
||||
// - win_hook_event
|
||||
//
|
||||
// static const wchar_t* events[] = { ll_keyboard,
|
||||
// win_hook_event,
|
||||
// nullptr };
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
// Return JSON with the configuration options.
|
||||
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
|
||||
{
|
||||
@ -232,25 +213,6 @@ public:
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
// Handle incoming event, data is event-specific
|
||||
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));
|
||||
// Return 1 if the keypress is to be suppressed (not forwarded to Windows),
|
||||
// otherwise return 0.
|
||||
return 0;
|
||||
}
|
||||
else if (wcscmp(name, win_hook_event) == 0)
|
||||
{
|
||||
auto& event = *(reinterpret_cast<WinHookEvent*>(data));
|
||||
// Return value is ignored
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Callback to send WM_CLOSE signal to each top level window.
|
||||
static BOOL CALLBACK requestMainWindowClose(HWND nextWindow, LPARAM closePid)
|
||||
{
|
||||
@ -274,11 +236,6 @@ public:
|
||||
TerminateProcess(m_hProcess, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register helper class to handle system menu items related actions. */
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) {}
|
||||
/* Handle action on system menu item. */
|
||||
virtual void signal_system_menu_action(const wchar_t* name) {}
|
||||
};
|
||||
|
||||
// Load the settings file.
|
||||
|
@ -183,13 +183,6 @@ public:
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
// Return array of the names of all events that this powertoy listens for, with
|
||||
// nullptr as the last element of the array. Nullptr can also be returned for empty list.
|
||||
virtual PCWSTR* get_events() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return JSON with the configuration options.
|
||||
// These are the settings shown on the settings page along with their current values.
|
||||
virtual bool get_config(_Out_ PWSTR buffer, _Out_ int* buffer_size) override
|
||||
@ -266,15 +259,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
// Handle incoming event, data is event-specific
|
||||
virtual intptr_t signal_event(const wchar_t* name, intptr_t data) override
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -1,6 +1,4 @@
|
||||
#include "pch.h"
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
#include <interface/win_hook_event_data.h>
|
||||
#include <settings_objects.h>
|
||||
#include <common.h>
|
||||
#include "powerpreview.h"
|
||||
@ -49,11 +47,6 @@ const wchar_t* PowerPreviewModule::get_name()
|
||||
return m_moduleName.c_str();
|
||||
}
|
||||
|
||||
const wchar_t** PowerPreviewModule::get_events()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return JSON with the configuration options.
|
||||
bool PowerPreviewModule::get_config(_Out_ wchar_t* buffer, _Out_ int* buffer_size)
|
||||
{
|
||||
@ -89,7 +82,6 @@ bool PowerPreviewModule::get_config(_Out_ wchar_t* buffer, _Out_ int* buffer_siz
|
||||
thumbnailProvider->GetToggleSettingState());
|
||||
}
|
||||
|
||||
|
||||
return settings.serialize_to_buffer(buffer, buffer_size);
|
||||
}
|
||||
|
||||
@ -182,12 +174,6 @@ bool PowerPreviewModule::is_enabled()
|
||||
return this->m_enabled;
|
||||
}
|
||||
|
||||
// Handle incoming event, data is event-specific
|
||||
intptr_t PowerPreviewModule::signal_event(const wchar_t* name, intptr_t data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Load the settings file.
|
||||
void PowerPreviewModule::init_settings()
|
||||
{
|
||||
@ -207,7 +193,6 @@ void PowerPreviewModule::init_settings()
|
||||
{
|
||||
thumbnailProvider->LoadState(settings);
|
||||
}
|
||||
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ private:
|
||||
// The PowerToy state.
|
||||
bool m_enabled = false;
|
||||
std::wstring m_moduleName;
|
||||
std::vector<FileExplorerPreviewSettings *> m_previewHandlers;
|
||||
std::vector<FileExplorerPreviewSettings*> m_previewHandlers;
|
||||
std::vector<FileExplorerPreviewSettings*> m_thumbnailProviders;
|
||||
|
||||
public:
|
||||
@ -39,8 +39,7 @@ public:
|
||||
GET_RESOURCE_STRING(IDS_PREVPANE_MD_SETTINGS_DESCRIPTION),
|
||||
L"{45769bcc-e8fd-42d0-947e-02beef77a1f5}",
|
||||
L"Markdown Preview Handler",
|
||||
new RegistryWrapper())
|
||||
}),
|
||||
new RegistryWrapper()) }),
|
||||
m_thumbnailProviders(
|
||||
{ // TODO: MOVE THIS SVG Thumbnail Provider settings object.
|
||||
new FileExplorerPreviewSettings(
|
||||
@ -49,22 +48,17 @@ public:
|
||||
GET_RESOURCE_STRING(IDS_SVG_THUMBNAIL_PROVIDER_SETTINGS_DESCRIPTION),
|
||||
L"{36B27788-A8BB-4698-A756-DF9F11F64F84}",
|
||||
L"SVG Thumbnail Provider",
|
||||
new RegistryWrapper())
|
||||
})
|
||||
new RegistryWrapper()) })
|
||||
{
|
||||
init_settings();
|
||||
};
|
||||
|
||||
virtual void destroy();
|
||||
virtual const wchar_t* get_name();
|
||||
virtual const wchar_t** get_events();
|
||||
virtual bool get_config(_Out_ wchar_t* buffer, _Out_ int* buffer_size);
|
||||
virtual void set_config(const wchar_t* config);
|
||||
virtual void enable();
|
||||
virtual void disable();
|
||||
virtual bool is_enabled();
|
||||
virtual void init_settings();
|
||||
virtual intptr_t signal_event(const wchar_t* name, intptr_t data);
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override {}
|
||||
virtual void signal_system_menu_action(const wchar_t* name) override {}
|
||||
};
|
@ -42,11 +42,6 @@ const wchar_t* OverlayWindow::get_name()
|
||||
return app_name.c_str();
|
||||
}
|
||||
|
||||
const wchar_t** OverlayWindow::get_events()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool OverlayWindow::get_config(wchar_t* buffer, int* buffer_size)
|
||||
{
|
||||
HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
|
||||
@ -213,11 +208,6 @@ bool OverlayWindow::is_enabled()
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
intptr_t OverlayWindow::signal_event(const wchar_t* name, intptr_t data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
intptr_t OverlayWindow::signal_event(LowlevelKeyboardEvent* event)
|
||||
{
|
||||
if (!_enabled)
|
||||
|
@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
#include "overlay_window.h"
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
#include <common/LowlevelKeyboardEvent.h>
|
||||
|
||||
// We support only one instance of the overlay
|
||||
extern class OverlayWindow* instance;
|
||||
|
||||
@ -16,7 +17,6 @@ public:
|
||||
OverlayWindow();
|
||||
|
||||
virtual const wchar_t* get_name() override;
|
||||
virtual const wchar_t** get_events() override;
|
||||
virtual bool get_config(wchar_t* buffer, int* buffer_size) override;
|
||||
|
||||
virtual void set_config(const wchar_t* config) override;
|
||||
@ -24,18 +24,11 @@ public:
|
||||
virtual void disable() override;
|
||||
virtual bool is_enabled() override;
|
||||
|
||||
// PowerToys interface method, not used
|
||||
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();
|
||||
void was_hidden();
|
||||
|
||||
// Method called from LowLevelKeyboardProc
|
||||
intptr_t signal_event(LowlevelKeyboardEvent* event);
|
||||
|
||||
virtual void destroy() override;
|
||||
|
@ -1,53 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "lowlevel_keyboard_event.h"
|
||||
#include "powertoys_events.h"
|
||||
#include <common/debug_control.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
HHOOK hook_handle = nullptr;
|
||||
HHOOK hook_handle_copy = nullptr; // make sure we do use nullptr in CallNextHookEx call
|
||||
LRESULT CALLBACK hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LowlevelKeyboardEvent event;
|
||||
if (nCode == HC_ACTION)
|
||||
{
|
||||
event.lParam = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
|
||||
event.wParam = wParam;
|
||||
if (powertoys_events().signal_event(ll_keyboard, reinterpret_cast<intptr_t>(&event)) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return CallNextHookEx(hook_handle_copy, nCode, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
void start_lowlevel_keyboard_hook()
|
||||
{
|
||||
#if defined(DISABLE_LOWLEVEL_HOOKS_WHEN_DEBUGGED)
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!hook_handle)
|
||||
{
|
||||
hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, hook_proc, GetModuleHandle(NULL), NULL);
|
||||
hook_handle_copy = hook_handle;
|
||||
if (!hook_handle)
|
||||
{
|
||||
throw std::runtime_error("Cannot install keyboard listener");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stop_lowlevel_keyboard_hook()
|
||||
{
|
||||
if (hook_handle)
|
||||
{
|
||||
UnhookWindowsHookEx(hook_handle);
|
||||
hook_handle = nullptr;
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
|
||||
void start_lowlevel_keyboard_hook();
|
||||
void stop_lowlevel_keyboard_hook();
|
@ -400,8 +400,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
{
|
||||
// Singletons initialization order needs to be preserved, first events and
|
||||
// then modules to guarantee the reverse destruction order.
|
||||
SystemMenuHelperInstance();
|
||||
powertoys_events();
|
||||
modules();
|
||||
|
||||
auto general_settings = load_general_settings();
|
||||
|
@ -22,7 +22,6 @@ PowertoyModule load_powertoy(const std::wstring_view filename)
|
||||
FreeLibrary(handle);
|
||||
winrt::throw_last_error();
|
||||
}
|
||||
module->register_system_menu_helper(&SystemMenuHelperInstance());
|
||||
return PowertoyModule(module, handle);
|
||||
}
|
||||
|
||||
@ -43,16 +42,4 @@ PowertoyModule::PowertoyModule(PowertoyModuleIface* module, HMODULE handle) :
|
||||
{
|
||||
throw std::runtime_error("Module not initialized");
|
||||
}
|
||||
auto want_signals = module->get_events();
|
||||
if (want_signals)
|
||||
{
|
||||
for (; *want_signals; ++want_signals)
|
||||
{
|
||||
powertoys_events().register_receiver(*want_signals, module);
|
||||
}
|
||||
}
|
||||
if (SystemMenuHelperInstance().HasCustomConfig(module))
|
||||
{
|
||||
powertoys_events().register_system_menu_action(module);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
#pragma once
|
||||
#include "powertoys_events.h"
|
||||
#include "system_menu_helper.h"
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
@ -16,8 +14,6 @@ struct PowertoyModuleDeleter
|
||||
{
|
||||
if (module)
|
||||
{
|
||||
powertoys_events().unregister_system_menu_action(module);
|
||||
powertoys_events().unregister_receiver(module);
|
||||
module->destroy();
|
||||
}
|
||||
}
|
||||
|
@ -1,105 +0,0 @@
|
||||
#include "pch.h"
|
||||
#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)
|
||||
start_lowlevel_keyboard_hook();
|
||||
else if (event == win_hook_event)
|
||||
start_win_hook_event();
|
||||
}
|
||||
|
||||
void last_unsubscribed(const std::wstring& event)
|
||||
{
|
||||
if (event == ll_keyboard)
|
||||
stop_lowlevel_keyboard_hook();
|
||||
else if (event == win_hook_event)
|
||||
stop_win_hook_event();
|
||||
}
|
||||
|
||||
PowertoysEvents& powertoys_events()
|
||||
{
|
||||
static PowertoysEvents powertoys_events;
|
||||
return powertoys_events;
|
||||
}
|
||||
|
||||
void PowertoysEvents::register_receiver(const std::wstring& event, PowertoyModuleIface* module)
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
auto& subscribers = receivers[event];
|
||||
if (subscribers.empty())
|
||||
{
|
||||
first_subscribed(event);
|
||||
}
|
||||
subscribers.push_back(module);
|
||||
}
|
||||
|
||||
void PowertoysEvents::unregister_receiver(PowertoyModuleIface* module)
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
for (auto& [event, subscribers] : receivers)
|
||||
{
|
||||
subscribers.erase(remove(begin(subscribers), end(subscribers), module), end(subscribers));
|
||||
if (subscribers.empty())
|
||||
{
|
||||
last_unsubscribed(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
SystemMenuHelperInstance().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)
|
||||
{
|
||||
SystemMenuHelperInstance().Customize(module, data.hwnd);
|
||||
}
|
||||
}
|
||||
else if (data.event == EVENT_OBJECT_INVOKED)
|
||||
{
|
||||
if (PowertoyModuleIface * module{ SystemMenuHelperInstance().ModuleFromItemId(data.idChild) })
|
||||
{
|
||||
std::wstring itemName = SystemMenuHelperInstance().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).
|
||||
SystemMenuHelperInstance().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);
|
||||
if (auto it = receivers.find(event); it != end(receivers))
|
||||
{
|
||||
for (auto& module : it->second)
|
||||
{
|
||||
if (module)
|
||||
rvalue |= module->signal_event(event.c_str(), data);
|
||||
}
|
||||
}
|
||||
return rvalue;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <interface/win_hook_event_data.h>
|
||||
#include <string>
|
||||
#include <shared_mutex>
|
||||
|
||||
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();
|
||||
|
||||
void first_subscribed(const std::wstring& event);
|
||||
void last_unsubscribed(const std::wstring& event);
|
@ -111,41 +111,33 @@
|
||||
<ClCompile Include="action_runner_utils.cpp" />
|
||||
<ClCompile Include="auto_start_helper.cpp" />
|
||||
<ClCompile Include="general_settings.cpp" />
|
||||
<ClCompile Include="lowlevel_keyboard_event.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="powertoys_events.cpp" />
|
||||
<ClCompile Include="powertoy_module.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="restart_elevated.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" />
|
||||
<ClCompile Include="update_utils.cpp" />
|
||||
<ClCompile Include="update_state.cpp" />
|
||||
<ClCompile Include="win_hook_event.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="action_runner_utils.h" />
|
||||
<ClInclude Include="auto_start_helper.h" />
|
||||
<ClInclude Include="general_settings.h" />
|
||||
<ClInclude Include="lowlevel_keyboard_event.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="update_utils.h" />
|
||||
<ClInclude Include="update_state.h" />
|
||||
<ClInclude Include="powertoys_events.h" />
|
||||
<ClInclude Include="powertoy_module.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="restart_elevated.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" />
|
||||
<ClInclude Include="win_hook_event.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="runner.rc" />
|
||||
|
@ -6,9 +6,6 @@
|
||||
<ClCompile Include="unhandled_exception_handler.cpp">
|
||||
<Filter>Utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="lowlevel_keyboard_event.cpp">
|
||||
<Filter>Events</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tray_icon.cpp">
|
||||
<Filter>Utils</Filter>
|
||||
</ClCompile>
|
||||
@ -27,15 +24,6 @@
|
||||
<ClCompile Include="general_settings.cpp">
|
||||
<Filter>Utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="powertoys_events.cpp">
|
||||
<Filter>Utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="win_hook_event.cpp">
|
||||
<Filter>Events</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="system_menu_helper.cpp">
|
||||
<Filter>Utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="restart_elevated.cpp">
|
||||
<Filter>Utils</Filter>
|
||||
</ClCompile>
|
||||
@ -54,9 +42,6 @@
|
||||
<ClInclude Include="unhandled_exception_handler.h">
|
||||
<Filter>Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="lowlevel_keyboard_event.h">
|
||||
<Filter>Events</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tray_icon.h">
|
||||
<Filter>Utils</Filter>
|
||||
</ClInclude>
|
||||
@ -75,15 +60,6 @@
|
||||
<ClInclude Include="general_settings.h">
|
||||
<Filter>Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="powertoys_events.h">
|
||||
<Filter>Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="win_hook_event.h">
|
||||
<Filter>Events</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="system_menu_helper.h">
|
||||
<Filter>Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="restart_elevated.h">
|
||||
<Filter>Utils</Filter>
|
||||
</ClInclude>
|
||||
@ -107,9 +83,6 @@
|
||||
<Filter Include="svgs">
|
||||
<UniqueIdentifier>{1123565f-43ba-4eb8-a6f5-2d5f8f3ae6af}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Events">
|
||||
<UniqueIdentifier>{d409b25e-c0f1-4913-bb32-da4a21339c76}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{74d0b535-16ee-46cc-9adf-dc4668bbcfda}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
@ -1,160 +0,0 @@
|
||||
#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& SystemMenuHelperInstance()
|
||||
{
|
||||
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 = (UINT)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"separator_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{};
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
#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& SystemMenuHelperInstance();
|
@ -1,90 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "win_hook_event.h"
|
||||
#include "powertoy_module.h"
|
||||
#include <mutex>
|
||||
#include <deque>
|
||||
#include <thread>
|
||||
|
||||
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,
|
||||
LONG object,
|
||||
LONG child,
|
||||
DWORD eventThread,
|
||||
DWORD eventTime)
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
hook_events.push_back({ event,
|
||||
window,
|
||||
object,
|
||||
child,
|
||||
eventThread,
|
||||
eventTime });
|
||||
lock.unlock();
|
||||
dispatch_cv.notify_one();
|
||||
}
|
||||
|
||||
static bool running = false;
|
||||
static std::thread dispatch_thread;
|
||||
static void dispatch_thread_proc()
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
while (running)
|
||||
{
|
||||
dispatch_cv.wait(lock, [] { return !running || !hook_events.empty(); });
|
||||
if (!running)
|
||||
return;
|
||||
while (!hook_events.empty())
|
||||
{
|
||||
auto event = hook_events.front();
|
||||
hook_events.pop_front();
|
||||
lock.unlock();
|
||||
intptr_t data = reinterpret_cast<intptr_t>(&event);
|
||||
intercept_system_menu_action(data);
|
||||
powertoys_events().signal_event(win_hook_event, data);
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static HWINEVENTHOOK hook_handle;
|
||||
|
||||
void start_win_hook_event()
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
if (running)
|
||||
return;
|
||||
running = true;
|
||||
dispatch_thread = std::thread(dispatch_thread_proc);
|
||||
hook_handle = SetWinEventHook(EVENT_MIN, EVENT_MAX, nullptr, win_hook_event_proc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
|
||||
}
|
||||
|
||||
void stop_win_hook_event()
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
if (!running)
|
||||
return;
|
||||
running = false;
|
||||
UnhookWinEvent(hook_handle);
|
||||
lock.unlock();
|
||||
dispatch_cv.notify_one();
|
||||
dispatch_thread.join();
|
||||
lock.lock();
|
||||
hook_events.clear();
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <interface/win_hook_event_data.h>
|
||||
|
||||
void start_win_hook_event();
|
||||
void stop_win_hook_event();
|
@ -1,7 +1,5 @@
|
||||
#include "pch.h"
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
#include <interface/win_hook_event_data.h>
|
||||
#include <common/settings_objects.h>
|
||||
#include "trace.h"
|
||||
|
||||
@ -74,23 +72,6 @@ public:
|
||||
return MODULE_NAME;
|
||||
}
|
||||
|
||||
// Return array of the names of all events that this powertoy listens for, with
|
||||
// nullptr as the last element of the array. Nullptr can also be returned for empty
|
||||
// list.
|
||||
virtual const wchar_t** get_events() override
|
||||
{
|
||||
static const wchar_t* events[] = { nullptr };
|
||||
// Available events:
|
||||
// - ll_keyboard
|
||||
// - win_hook_event
|
||||
//
|
||||
// static const wchar_t* events[] = { ll_keyboard,
|
||||
// win_hook_event,
|
||||
// nullptr };
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
// Return JSON with the configuration options.
|
||||
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
|
||||
{
|
||||
@ -228,34 +209,6 @@ public:
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
// Handle incoming event, data is event-specific
|
||||
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));
|
||||
// Return 1 if the keypress is to be suppressed (not forwarded to Windows),
|
||||
// otherwise return 0.
|
||||
return 0;
|
||||
}
|
||||
else if (wcscmp(name, win_hook_event) == 0)
|
||||
{
|
||||
auto& event = *(reinterpret_cast<WinHookEvent*>(data));
|
||||
// Return value is ignored
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This methods are part of an experimental features not fully supported yet
|
||||
virtual void register_system_menu_helper(PowertoySystemMenuIface* helper) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void signal_system_menu_action(const wchar_t* name) override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Load the settings file.
|
||||
|
Loading…
Reference in New Issue
Block a user