pcsx2/3rdparty/winwil/include/wil/windowing.h

164 lines
5.7 KiB
C++

//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
//*********************************************************
#ifndef __WIL_WINDOWING_INCLUDED
#define __WIL_WINDOWING_INCLUDED
#include <WinUser.h>
#include <exception>
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
namespace wil
{
namespace details
{
template <typename T>
struct always_false : wistd::false_type
{
};
template <typename TEnumApi, typename TCallback>
void DoEnumWindowsNoThrow(TEnumApi&& enumApi, TCallback&& callback) noexcept
{
auto enumproc = [](HWND hwnd, LPARAM lParam) -> BOOL {
auto pCallback = reinterpret_cast<TCallback*>(lParam);
#ifdef __cpp_if_constexpr
using result_t = decltype((*pCallback)(hwnd));
if constexpr (wistd::is_void_v<result_t>)
{
(*pCallback)(hwnd);
return TRUE;
}
else if constexpr (wistd::is_same_v<result_t, HRESULT>)
{
// NB: this works for both HRESULT and NTSTATUS as both S_OK and ERROR_SUCCESS are 0
return (S_OK == (*pCallback)(hwnd)) ? TRUE : FALSE;
}
else if constexpr (std::is_same_v<result_t, bool>)
{
return (*pCallback)(hwnd) ? TRUE : FALSE;
}
else
{
static_assert(details::always_false<TCallback>::value, "Callback must return void, bool, or HRESULT");
}
#else
return (*pCallback)(hwnd);
#endif
};
enumApi(enumproc, reinterpret_cast<LPARAM>(&callback));
}
#ifdef WIL_ENABLE_EXCEPTIONS
template <typename TEnumApi, typename TCallback>
void DoEnumWindows(TEnumApi&& enumApi, TCallback&& callback)
{
struct
{
std::exception_ptr exception;
TCallback* pCallback;
} callbackData = {nullptr, &callback};
auto enumproc = [](HWND hwnd, LPARAM lParam) -> BOOL {
auto pCallbackData = reinterpret_cast<decltype(&callbackData)>(lParam);
try
{
auto pCallback = pCallbackData->pCallback;
#ifdef __cpp_if_constexpr
using result_t = decltype((*pCallback)(hwnd));
if constexpr (std::is_void_v<result_t>)
{
(*pCallback)(hwnd);
return TRUE;
}
else if constexpr (std::is_same_v<result_t, HRESULT>)
{
// NB: this works for both HRESULT and NTSTATUS as both S_OK and ERROR_SUCCESS are 0
return (S_OK == (*pCallback)(hwnd)) ? TRUE : FALSE;
}
else if constexpr (std::is_same_v<result_t, bool>)
{
return (*pCallback)(hwnd) ? TRUE : FALSE;
}
else
{
static_assert(details::always_false<TCallback>::value, "Callback must return void, bool, or HRESULT");
}
#else
return (*pCallback)(hwnd);
#endif
}
catch (...)
{
pCallbackData->exception = std::current_exception();
return FALSE;
}
};
enumApi(enumproc, reinterpret_cast<LPARAM>(&callbackData));
if (callbackData.exception)
{
std::rethrow_exception(callbackData.exception);
}
}
#endif
} // namespace details
template <typename TCallback>
void for_each_window_nothrow(TCallback&& callback) noexcept
{
details::DoEnumWindowsNoThrow(&EnumWindows, wistd::forward<TCallback>(callback));
}
template <typename TCallback>
void for_each_thread_window_nothrow(_In_ DWORD threadId, TCallback&& callback) noexcept
{
auto boundEnumThreadWindows = [threadId](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL {
return EnumThreadWindows(threadId, enumproc, lParam);
};
details::DoEnumWindowsNoThrow(boundEnumThreadWindows, wistd::forward<TCallback>(callback));
}
template <typename TCallback>
void for_each_child_window_nothrow(_In_ HWND hwndParent, TCallback&& callback) noexcept
{
auto boundEnumChildWindows = [hwndParent](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL {
return EnumChildWindows(hwndParent, enumproc, lParam);
};
details::DoEnumWindowsNoThrow(boundEnumChildWindows, wistd::forward<TCallback>(callback));
}
#ifdef WIL_ENABLE_EXCEPTIONS
template <typename TCallback>
void for_each_window(TCallback&& callback)
{
details::DoEnumWindows(&EnumWindows, wistd::forward<TCallback>(callback));
}
template <typename TCallback>
void for_each_thread_window(_In_ DWORD threadId, TCallback&& callback)
{
auto boundEnumThreadWindows = [threadId](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL {
return EnumThreadWindows(threadId, enumproc, lParam);
};
details::DoEnumWindows(boundEnumThreadWindows, wistd::forward<TCallback>(callback));
}
template <typename TCallback>
void for_each_child_window(_In_ HWND hwndParent, TCallback&& callback)
{
auto boundEnumChildWindows = [hwndParent](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL {
return EnumChildWindows(hwndParent, enumproc, lParam);
};
details::DoEnumWindows(boundEnumChildWindows, wistd::forward<TCallback>(callback));
}
#endif
} // namespace wil
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#endif // __WIL_WINDOWING_INCLUDED