mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-12-15 03:59:15 +08:00
be86cd4028
Document new interface changes.
83 lines
2.5 KiB
C++
83 lines
2.5 KiB
C++
#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);
|
|
}
|
|
}
|